Проверка, равен ли двойное значение -0,00 - PullRequest
0 голосов
/ 06 ноября 2018

Я делаю эту большую программу на C, которая является частью моей домашней работы. Моя проблема в том, что моя программа выводит x = -0.00 вместо x = 0.00. Я пробовал сравнивать как if(x==-0.00) x=fabs(x), но я читал, что это не сработает с дублями. Поэтому мой вопрос: есть ли другие способы проверить, равен ли double отрицательный ноль?

Ответы [ 5 ]

0 голосов
/ 06 ноября 2018

Чтобы всегда получать неотрицательную версию, вам вообще не нужно сравнение. Вы можете принять абсолютное значение все время. Если значение неотрицательное, fabs должно вернуть исходное значение.

0 голосов
/ 06 ноября 2018

Здесь вам нужно две функции.

Во-первых, функция signbit может сообщить вам, установлен ли бит знака на число с плавающей запятой. Во-вторых, функция fpclassify сообщит вам, является ли число с плавающей точкой какой-либо формой 0.

Например:

double x = 0.0;
double y = -0.0;
double a = 3;
double b = -2;
printf("x=%f, y=%f\n", x, y);
printf("x is zero: %d\n", (fpclassify(x) == FP_ZERO));
printf("y is zero: %d\n", (fpclassify(y) == FP_ZERO));
printf("a is zero: %d\n", (fpclassify(a) == FP_ZERO));
printf("b is zero: %d\n", (fpclassify(b) == FP_ZERO));
printf("x sign: %d\n", signbit(x));
printf("y sign: %d\n", signbit(y));
printf("a sign: %d\n", signbit(a));
printf("b sign: %d\n", signbit(b));

Выход:

x=0.000000, y=-0.000000
x is zero: 1
y is zero: 1
a is zero: 0
b is zero: 0
x sign: 0
y sign: 1
a sign: 0
b sign: 1

Чтобы проверить, является ли значение отрицательным нулем, выполните следующие действия:

if (fpclassify(x) == FP_ZERO)) {
    if (signbit(x)) {
        printf("x is negative zero\n");
    } else {
        printf("x is positive zero\n");
    }
}
0 голосов
/ 06 ноября 2018

Вы можете использовать стандартный макрос signbit(arg) из math.h. Он вернет ненулевое значение, если arg отрицательно и 0 в противном случае.

со страницы руководства :

signbit() - это универсальный макрос, который может работать на всех реальных плавающих Типы точек. Возвращает ненулевое значение, если значение x имеет бит знака установлен.

Это не то же самое, что x <0.0, потому что IEEE 754 с плавающей запятой позволяет ноль быть подписанным. <strong>Сравнение -0.0 <0.0 неверно, но signbit (-0.0) вернет ненулевое значение </strong>.

У NaN и бесконечностей есть знаковый бит.

Также с cppreference.com :

Этот макрос обнаруживает знаковый бит нулей, бесконечностей и NaN. Вместе с copysign этот макрос является одним из двух переносимых способов осмотрите знак NaN.

0 голосов
/ 06 ноября 2018

Скорее всего, ваша программа имеет небольшое отрицательное значение, а не ноль, которое printf форматируется как «-0.00». Чтобы напечатать такие числа, как «0,00», вы можете проверить, как printf отформатирует их и заменит нежелательную строку на желаемую строку:

#include <stdio.h>
#include <string.h>

void PrintAdjusted(double x)
{
    char buffer[6];
    int result = snprintf(buffer, sizeof buffer, "%.2f", x);

    /* If snprintf produces a result other than "-0.00", including
       a result that does not fit in the buffer, use it.
       Otherwise, print "0.00".
    */
    if (sizeof buffer <= result || strcmp(buffer, "-0.00") != 0)
        printf("%.2f", x);
    else
        printf("0.00");
}

Это портативный. Альтернативы, такие как сравнение числа с -0.005, имеют проблемы с переносимостью из-за зависящих от реализации деталей в форматах с плавающей запятой и методов округления в printf.

Если вы действительно хотите проверить, является ли число x значением -0, вы можете использовать:

#include <math.h>
…
signbit(x) && x == 0
0 голосов
/ 06 ноября 2018

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

Обратите внимание, что -0.0 определено равным 0.0, поэтому простого сравнения с 0.0 достаточно для проверки нуля со знаком.

Если вы хотите преобразовать точный ноль со знаком -0.0 в 0.0, добавьте к нему 0.0.

...