Как преобразовать отрицательный ноль в положительный ноль в C? - PullRequest
16 голосов
/ 11 марта 2012

Здравствуйте, я изучаю Цель C, и я делал классический пример Калькулятора.

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

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

(gdb) печать -2 * 0
$ 1 = 0

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

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

Ответы [ 5 ]

13 голосов
/ 11 марта 2012

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

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;
5 голосов
/ 11 марта 2012

http://en.wikipedia.org/wiki/Signed_zero

Число 0 обычно кодируется как +0, но может быть представлено как +0 или -0

Это не должно влиятьпо расчетам или выводу пользовательского интерфейса.

3 голосов
/ 22 июня 2017

Здесь недопонимание относительно приоритета оператора:

(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 более простое решение для IEC60559 соответствующих сред:

d = d + 0.0;  // turn -0.0 to +0.0
2 голосов
/ 22 июня 2017

Как я могу это исправить в моем приложении?

Код действительно не сломан, поэтому ничего не нужно «исправлять». @ 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, которое может иметь любое значение, трудно превзойти следующее. @ Ричард Дж. Росс III @ chqrlie Подход x + 0.0 имеет преимущество в том, что, вероятно, не вводит ветвь, но следующее ясно.

if (x == 0.0) x = 0.0;

Примечание: fmax(-0.0, 0.0) может выдавать -0,0.

0 голосов
/ 13 мая 2019

В моем коде (на компиляторе C MPI Intel) -0.0 и +0.0 не совпадают.

Как пример:

d = -0.0
if (d < 0.0)
    do something...

и он делает это "что-то".

также добавляем -0.0 + 0.0 = -0.0...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...