Правильный способ сравнить System.Double с '0' (число, int?)
Извините, это может быть очень глупый вопрос, но я должен знать, чтобы быть уверенным.
У меня есть это выражение 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.
Ответы
Ответ 1
Ну, как близко вам нужно значение, которое должно быть 0? Если вы пройдете множество операций с плавающей запятой, которые в "бесконечной точности" могут привести к 0, вы можете получить результат "очень близко" к 0.
Обычно в этой ситуации вы хотите предоставить какой-то epsilon и убедитесь, что результат находится только внутри этого epsilon:
if (Math.Abs(something) < 0.001)
Эпсилон, который вы должны использовать, зависит от приложения - это зависит от того, что вы делаете.
Конечно, если результат должен быть ровно равным нулю, то простая проверка равенства отлично.
Ответ 2
Ваш something
- это double
, и вы правильно определили, что в строке
if (something == 0)
имеем a double
в левой части (lhs) и a int
в правой части (rhs).
Но теперь кажется, что вы думаете, что lhs будет преобразовано в int
, а затем знак ==
будет сравнивать два целых числа. Это не, что происходит. Преобразование из double
в int
является явным и не может быть "автоматически".
Вместо этого происходит обратное. Rhs преобразуется в double
, а затем знак ==
становится тестом равенства между двумя двойниками. Это преобразование неявно (автоматически).
Считается лучше (кем-то) писать
if (something == 0.0)
или
if (something == 0d)
потому что тогда сразу же вы сравниваете два удвоения. Однако это просто вопрос стиля и удобочитаемости, поскольку компилятор будет делать то же самое в любом случае.
В некоторых случаях также важно ввести "толерантность", как в ответе Джона Скита, но эта толерантность также будет double
. Он мог, конечно, быть 1.0
, если вы этого хотели, но это не должно быть [наименее строго положительное] целое число.
Ответ 3
Если something
был назначен из результата операции, отличной от something = 0
, вам лучше использовать:
if(Math.Abs(something) < Double.Epsilon)
{
//do something
}
Ответ 4
Если вы просто хотите подавить предупреждение, сделайте следующее:
if (something.Equals(0.0))
Конечно, это только действительное решение, если вы знаете, что дрифт не вызывает беспокойства. Я часто делаю это, чтобы проверить, собираюсь ли я делить на ноль.
Ответ 5
Я не думаю, что это честно. Рассмотрим собственный пример yuor: something = 0,9 или 0,0004.
В первом случае это будет ЛОЖЬ, во втором случае это будет ИСТИНА. При работе с этими типами я обычно определяю для меня прецизионный процент и сравниваю в пределах этой точности.
Зависит от ваших потребностей.
что-то вроде...
if(((int)(something*100)) == 0) {
//do something
}
Надеюсь, что это поможет.