Правильный способ сравнения системы.Удвоить до ' 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.

5 73

5 ответов:

Ну, как близко вам нужно значение, чтобы быть 0? Если вы пройдете через множество операций с плавающей запятой, которые в "бесконечной точности" могут привести к 0, вы можете получить результат "очень близко" к 0.

обычно в этой ситуации вы хотите предоставить какой-то Эпсилон и проверить, что результат находится именно в этом Эпсилоне:

if (Math.Abs(something) < 0.001)

Эпсилон, который вы должны использовать, зависит от приложения-это зависит от того, что вы делаете.

конечно, если результат должен быть ровно ноль, тогда простая проверка равенства в порядке.

Если something был назначен из результата операции, отличной от something = 0 тогда вам лучше использовать:

if(Math.Abs(something) < Double.Epsilon)
{
//do something
}

Edit: этот код неверен. Эпсилон-это наименьшее число, но не совсем ноль. Когда вы хотите сравнить число с другим числом, вам нужно подумать о том, что такое приемлемый допуск. Допустим, что-нибудь за ее пределами .00001 тебя это не волнует. Это номер, который вы бы использовали. Значение зависит от домена. Тем не менее, это в основном конечно, никогда не удваивается.Ипсилон.

код something - это double, а вы правильно определили, что в строке

if (something == 0)

у нас есть double на левой стороне (lhs) и int на правой стороне (rhs).

но теперь кажется, что вы думаете, что lhs будет преобразован в int, а потом == знак будет сравнивать два целых числа. Это не что происходит. Преобразование Сdoubleдоint is явно и не может произойти "автоматически".

вместо этого происходит обратное. РГО превращается в 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
}

надеюсь, что это помогает.