Подтвердить что ты не робот

Вы можете сравнить значения с плавающей запятой точно до нуля?

Я знаю, что мы не можем сравнивать 2 значения с плавающей запятой, используя ==. Мы можем только сравнить, что они находятся в некотором интервале друг от друга. Я знаю

if(val == 0.512)

неверно из-за ошибок, присущих вычислениям с плавающей запятой и преобразованию в двоичные и должно быть

if (val in (0.512-epsilon, 0.512+epsilon))

Но 0 особенный? Можно ли сравнивать поплавки с точностью до 0? Или это неверно? В частности, в контексте С# и Java?

double val = 0;
val = getVal();
if(val == 0)
4b9b3361

Ответ 1

Несмотря на то, что 0 имеет точное представление, вы не можете рассчитывать на результат вычисления с использованием float точно в 0. Как вы отметили, это связано с вычислениями с плавающей точкой и проблемами с конверсией.

Итак, вы должны протестировать 0 против вашего толерантного эпсилона.

Ответ 2

Используйте подход допуска/ephsilon.

Я просто оценил следующее в Java, которое математически приводит к нулю:

1.0/5.0 + 1.0/5.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0

и фактически получил

2.7755575615628914E-17

Ответ 3

Вы можете сравнить с нолем, если вы назначили эту переменную ноль. Если вы получаете нуль, например. вычитание вы все равно можете получить очень малое число, близкое к нулю. например: 0,1-0,1, может быть эквивалентно примерно 1е-9.

Ответ 4

Для сравнения с err все, что вам нужно, это.

// compare a and b with an ERR error.
if (Math.abs(a - b) <= ERR)

Для сравнения с 0

// compare a and 0 with an ERR error.
if (Math.abs(a) <= ERR)

Ответ 5

Поскольку нуль имеет точное представление, возможно сравнение значения == с нолем. Если переменная, которую вы тестируете, была задана назначением или из введенного значения (например, getVal в вашем примере?), Оно может быть легко равным нулю. Но если это был результат расчета, вероятность того, что он будет ровно нулем, очень мала. Это усугубляется тем, что обычные десятичные дроби, такие как 0,2, не имеют точного представления в плавающей точке. Именно поэтому лучше всего использовать эпсилон.

Ответ 6

Я по-прежнему рекомендую следовать идолам допуска и не сравнивать с нулем точно.

Ответ 7

Я не думаю, что вы можете вообще - расчет, который происходит в getVal(), может логически привести к нулю, но это не означает, что он вернет ноль. Если вы объясните, возвращаете ноль, чтобы указать какое-то условие, то сравнение всегда должно работать, но я не думаю, что это была бы лучшая практика. Я бы изменил функцию, чтобы вернуть код состояния и передать значение, которое нужно изменить byref.

Ответ 8

В любой нетривиальной ситуации вы действительно должны использовать только подход толерантности. Как уже отмечалось, нулевое сравнение является точным только тогда, когда вы фактически присвоили его нулю.

Не повторяя того, что говорили другие, я просто хочу подчеркнуть тот факт, что использование подхода толерантности более будущего доказательства. То, что вы когда-то считали простым назначением, может включать в себя фактическую арифметику позже. Использование голого сравнения затрудняет отладку позже.