Как преобразовать отрицательный ноль в положительный ноль в C?

Привет, я изучаю Objective C, и я делал classический пример калькулятора.

Проблема в том, что я получаю отрицательный ноль, когда я умножаю ноль на любое отрицательное число, и я ставил результат в (двойной) тип!

Чтобы посмотреть, что происходит, я играл с отладчиком, и это то, что я получил:

(gdb) print -2 * 0
$ 1 = 0

(gdb) print (double) -2 * 0
$ 2 = -0

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

Я сделал простой тест:

 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 к вашему приложению:

 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 Standard указано как поведение Unspecifier. Независимо от того, могут ли определенные операторы генерировать отрицательные нули и равен ли отрицательный ноль нормальному нулю при хранении в объекте (6.2.6.2).

И наоборот, (double)(-2 * 0) должен генерировать положительный нуль 0.0 на большинстве современных платформ, поскольку умножение выполняется с использованием целочисленной арифметики. Стандарт C имеет поддержку архитектур, которые отличают положительные и отрицательные целые числа нhive, но в настоящее время они исчезающе редки.

Если вы хотите, чтобы нули были положительными, это простое исправление должно работать:

 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  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.