Умножает ли число с плавающей запятой на 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
}
Вот почему почти всегда рекомендуется не использовать точное равенство при сравнении значений с плавающей запятой.