Умножает ли число с плавающей запятой на 0 всегда 0?

Числа с плавающей запятой хитрые, так как многие естественные арифметические свойства не выполняются.

Я полагаю, что это конкретное свойство, тем не менее, сохраняется, но я предпочитаю спрашивать, а не подвергаться жестким обнаружениям ошибок.

Предположим, что d произвольная переменная типа double, Могу ли я предположить, что после следующей операции:

d *= 0;

Следующая проверка всегда вернется true?

d == 0

Я полагаю, что это не будет иметь место, если d является положительной / отрицательной бесконечностью или NaN. Однако есть ли другие проблемы, о которых мне нужно знать?

  • Я слышал, что в плавающей точке на самом деле есть два нуля, а именно +0 а также -0, Если d отрицателен в начале, будет d *= 0 вернуть -0 вместо? Если так, будет ли он равен 0?
  • Я слышал, что операции с плавающей запятой подвержены неточности. Таким образом, возможно ли, что умножение на 0 вместо этого вернет что-то вроде 0.0000001 или же -0.000001 который не будет равен 0? Я предполагаю, что это, вероятно, будет невозможно, но у меня недостаточно знаний, чтобы подтвердить это предположение, поэтому я предпочитаю спросить.
  • Какие-нибудь другие проблемы, которые я не предвидел?

1 ответ

Краткий ответ - да, учитывая ваш конкретный пример, d будет 0. Это потому, что 0 имеет точное представление в каждой модели FP, поэтому, когда вы умножаете double на значение '0' (или '0.0'), результат не подлежит ошибкам округления / усечения.

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

Например, наиболее точное 64-разрядное представление значения 0,002 в стандарте IEEE-754 - это 0x3F60624D_D2F1A9FC, что составляет 2,00000000000000004163336342344E-3 (источник: http://www.binaryconvert.com/convert_double.html).

Значение 0 не страдает от этой потери точности. Однако, очевидно, что если вы сделаете что-то подобное, вы столкнетесь с проблемами:

double d = 0.009;
d -= (0.001 * 9);
if (d == 0)
{
    //This check will fail
}

Вот почему почти всегда рекомендуется не использовать точное равенство при сравнении значений с плавающей запятой.

Другие вопросы по тегам