Я знаю, что обычно нельзя полагаться на равенство между значениями типа double или decimal, но мне интересно, является ли 0 особым случаем.
Хотя я могу понять неточности между 0,00000000000001 и 0,00000000000002, само значение 0 кажется довольно сложным, поскольку это просто ничего. Если вы неточны ни в чем, это уже не ничто.
Но я не очень разбираюсь в этой теме, поэтому не мне говорить.
double x = 0.0;
return (x == 0.0) ? true : false;
Всегда ли это будет верным?
Ответы:
Можно с уверенностью ожидать, что сравнение вернется
true
тогда и только тогда, когда переменная double имеет значение точно0.0
(что, конечно же, имеет место в исходном фрагменте кода). Это соответствует семантике==
оператора.a == b
означает «a
равноb
».Это не безопасно (потому что это не правильно ) ожидать , что результат некоторого расчета будет равен нуль в двойной (или в более общем плане , с плавающей точкой) арифметики , когда результат такого же расчет в чистой математике равен нуль. Это связано с тем, что, когда вычисления происходят на земле, появляется ошибка точности с плавающей запятой - концепция, которой нет в арифметике вещественных чисел в математике.
источник
Если вам нужно провести много сравнений «на равенство», было бы неплохо написать небольшую вспомогательную функцию или метод расширения в .NET 3.5 для сравнения:
Это можно было бы использовать следующим образом:
источник
Для вашего простого образца этот тест подходит. А как насчет этого:
Помните, что .1 - это повторяющееся десятичное число в двоичном формате и не может быть представлено точно. Затем сравните это с этим кодом:
Я оставлю вас провести тест, чтобы увидеть фактические результаты: вы, скорее всего, так запомните.
источник
Из записи MSDN для Double.Equals :
Также см. Double.Epsilon .
источник
x.Equals(y)
, то(1/x).Equals(1/y)
, но это не тот случай, еслиx
есть0
иy
есть1/Double.NegativeInfinity
. Эти значения объявляются равными, хотя их обратные значения не совпадают.x = 0
иy = 0
, и вы все равно найдете это1/x != 1/y
.x
иy
как типаdouble
? Как вы сравниваете результаты, чтобы они сообщали о неравенстве? Обратите внимание, что 1 / 0,0 не является NaN.1.0/0.0
не NaN, каким должно быть, поскольку предел не уникален. Во-вторых, бесконечности сравниваются как равные друг другу, не обращая внимания на степени бесконечности)Проблема возникает, когда вы сравниваете различные типы реализации значений с плавающей запятой, например, сравнение float с double. Но с таким же типом проблем быть не должно.
Проблема в том, что программист иногда забывает, что для сравнения происходит неявное приведение типа (двойное к float), что приводит к ошибке.
источник
Если число было напрямую назначено для числа с плавающей запятой или двойной точности, то можно безопасно протестировать против нуля или любого целого числа, которое может быть представлено 53 битами для числа double или 24 битами для числа с плавающей запятой.
Или, говоря другими словами, вы всегда можете присвоить целочисленное значение двойному, а затем сравнить двойное с тем же целым числом и гарантировать, что оно будет равным.
Вы также можете начать с присвоения целого числа, и простые сравнения продолжат работать, придерживаясь сложения, вычитания или умножения на целые числа (при условии, что результат меньше 24 бит для числа с плавающей запятой и 53 бита для двойного). Таким образом, вы можете рассматривать числа с плавающей запятой и двойные числа как целые при определенных контролируемых условиях.
источник
Нет, это не нормально. Так называемые денормализованные значения (субнормальные) при сравнении равных 0,0 будут сравниваться как ложные (ненулевые), но при использовании в уравнении будут нормализованы (станут 0,0). Таким образом, использовать это как механизм, позволяющий избежать деления на ноль, небезопасно. Вместо этого добавьте 1,0 и сравните с 1,0. Это гарантирует, что все субнормальные значения будут считаться нулевыми.
источник
Попробуйте это, и вы обнаружите, что == ненадежно для double / float.
double d = 0.1 + 0.2; bool b = d == 0.3;
Вот ответ от Quora.
источник
На самом деле, я думаю, что для сравнения двойного значения с 0,0 лучше использовать следующие коды:
То же самое для поплавка:
источник