Извините, это может быть простой глупый вопрос, но мне нужно знать, чтобы быть уверенным.
У меня есть это if
выражение,
void Foo()
{
System.Double something = GetSomething();
if (something == 0) //Comparison of floating point numbers with equality
// operator. Possible loss of precision while rounding value
{}
}
Это выражение равно
void Foo()
{
System.Double something = GetSomething();
if (something < 1)
{}
}
? Потому что тогда у меня может возникнуть проблема, если ввести, if
например, значение 0,9.
// Comparison of floating point numbers with equality // operator.
Вам действительно нужно было это указать? :)Ответы:
Ну, насколько близко вам нужно, чтобы значение было 0? Если вы выполняете множество операций с плавающей запятой, которые при «бесконечной точности» могут привести к 0, вы можете получить результат «очень близкий» к 0.
Обычно в этой ситуации вы хотите предоставить какой-то эпсилон и проверить, что результат находится именно в этом эпсилоне:
if (Math.Abs(something) < 0.001)
Эпсилон, который вы должны использовать, зависит от приложения - это зависит от того, что вы делаете.
Конечно, если результат должен быть точно равен нулю, тогда подойдет простая проверка на равенство.
источник
== 0
. У вас есть буквальное значение - это довольно постоянно :)Если
something
он был назначен в результате другой операции, чемsomething = 0
тогда, вам лучше использовать:if(Math.Abs(something) < Double.Epsilon) { //do something }
Изменить : этот код неверен. Эпсилон - наименьшее число, но не совсем ноль. Если вы хотите сравнить одно число с другим числом, вам нужно подумать о том, каков допустимый допуск. Допустим, вам все равно, что больше 0,00001. Это номер, который вы бы использовали. Значение зависит от домена. Однако Double.Epsilon, как правило, никогда не бывает.
источник
Math.Abs(0.1f - 0.1d) < double.Epsilon
этоfalse
double d = Math.Sqrt(10100)*2; double a = Math.Sqrt(40400); if(Math.Abs(a - d) < double.Epsilon) { Console.WriteLine("true"); }
Ваш
something
- этоdouble
, и вы правильно определили, что в строкеif (something == 0)
у нас есть
double
слева (lhs) и anint
справа (rhs).Но теперь кажется, что вы думаете, что lhs будет преобразовано в
int
, а затем==
знак будет сравнивать два целых числа. Это не то, что происходит. Преобразование изdouble
вint
является явным и не может происходить «автоматически».Вместо этого происходит обратное. Правая часть преобразуется в
double
, а затем==
знак становится проверкой равенства между двумя двойными числами. Это преобразование неявное (автоматическое).Некоторые считают, что лучше написать
if (something == 0.0)
или
if (something == 0d)
потому что тогда сразу же вы сравниваете два дубля. Однако это всего лишь вопрос стиля и удобочитаемости, потому что компилятор в любом случае будет делать то же самое.
В некоторых случаях также уместно ввести «толерантность», как в ответе Джона Скита, но эта толерантность тоже будет
double
. Конечно, может быть,1.0
если вы захотите, но это не обязательно должно быть [наименее строго положительное] целое число.источник
Если вы просто хотите подавить предупреждение, сделайте следующее:
if (something.Equals(0.0))
Конечно, это верное решение, только если вы знаете, что дрейф не имеет значения. Я часто делаю это, чтобы проверить, не собираюсь ли делить на ноль.
источник
Честно говоря, я не думаю, что это равнозначно. Рассмотрим ваш собственный пример: something = 0,9 или 0,0004. В первом случае это будет ЛОЖЬ, во втором - ИСТИНА. Имея дело с этими типами, я обычно определяю процент точности и сравниваю с этой точностью. Зависит от ваших потребностей. что-то типа...
if(((int)(something*100)) == 0) { //do something }
Надеюсь это поможет.
источник
Вот пример, представляющий проблему (подготовленный в LinQPad - если у вас его нет, просто используйте
Console.Writeline
вместоDump
метода):void Main() { double x = 0.000001 / 0.1; double y = 0.001 * 0.01; double res = (x-y); res.Dump(); (res == 0).Dump(); }
И x, и y теоретически одинаковы и равны: 0,00001, но из-за отсутствия «бесконечной точности» эти значения немного отличаются. К сожалению, достаточно немного, чтобы вернуться
false
при сравнении с 0 обычным способом.источник