Отрицательный ноль в C
Привет, я изучаю цель C, и я делал классический пример калькулятора.
проблема в том, что я получаю отрицательный ноль, когда я умножаю ноль на любое отрицательное число, и я помещаю результат в (двойной) тип!
чтобы увидеть, что происходит, я играл с отладчиком, и вот что я получил:
(gdb) печать -2 * 0
$1 = 0(gdb) печать (двойной) -2 * 0
2 $ = -0
в второй случай, когда я бросил его на двойной тип, он превращается в отрицательный ноль! Как я могу исправить это в своем приложении? Мне нужно работать с двойниками. Как я могу исправить результат, чтобы получить ноль, когда результат должен быть равен нулю?
спасибо заранее.
4 ответов
Я сделал простой тест:
double d = (double) -2.0 * 0;
if (d < 0)
printf("d is less than zero\n");
if (d == 0)
printf("d is equal to zero\n");
if (d > 0)
printf("d is greater than zero\n");
printf("d is: %lf\n", d);
выдает:
d равно нулю
d является: -0.000000
Итак, чтобы исправить это, вы можете добавить простой if-check в свое приложение:
if (d == 0) d = 0;
http://en.wikipedia.org/wiki/Signed_zero
число 0 обычно кодируется как +0, но может быть представлено либо +0, либо -0
Это не должно влиять на вычисления или вывод пользовательского интерфейса.
здесь есть недоразумение о приоритете оператора:
(double) -2 * 0
анализируется как
((double)(-(2))) * 0
что по существу то же самое, что (-2.0) * 0.0
.
в C стандартные информационное приложение J перечислены как поведение Unspecifier могут ли определенные операторы генерировать отрицательные нули и становится ли отрицательный нуль нормальным нулем при хранении в объекте (6.2.6.2).
наоборот, (double)(-2 * 0)
должен генерировать положительный ноль 0.0
на большинстве современных платформ, так как умножение выполняется с использованием целочисленной арифметики. Стандарт C поддерживает архитектуры, которые различают положительные и отрицательные нулевые целые числа, но в настоящее время они исчезающе редки.
если вы хотите заставить нули быть положительными, это простое исправление должно работать:
if (d == 0) {
d = 0;
}
вы могли бы сделать намерение яснее с этого:
if (d == -0.0) {
d = +0.0;
}
но тест также будет успешным, если d
положительный нуль.
Chux имеет более простое решение для IEC 60559 исполняя окружающих сред:
d = d + 0.0; // turn -0.0 to +0.0
как я могу исправить это в моем приложении?
код действительно не сломан, поэтому ничего не нужно "исправлять". @kennytm
как я могу исправить результат, чтобы получить ноль, когда результат должен быть равен нулю?
чтобы легко избавиться от -
когда результат -0.0
добавьте 0.0
. Код после стандартных (IEC 60559 с плавающей запятой) правил будет производить падение -
знак.
double nzero = -0.0;
printf("%f\n", nzero);
printf("%f\n", nzero + 0.0);
printf("%f\n", fabs(nzero)); // This has a side effect of changing all negative values
// pedantic code using <math.h>
if (signbit(nzero)) nzero = 0.0; // This has a side effect of changing all negative values
printf("%f\n", nzero);
обычный выходной.
-0.000000
0.000000
0.000000
0.000000
но для общего double x
что может иметь любое значение, трудно превзойти следующее. @Richard J. Ross III @chqrlie на x + 0.0
подход имеет преимущество в том, что, вероятно, не вводит ветку, но следующее ясно.
if (x == 0.0) x = 0.0;
Примечание: fmax(-0.0, 0.0)
может производить -0.0.