Checking if a double is equal to -0.00

Viewed 324

I am making this big program in C, which is a part of my homework. My problem is that my program is outputing x = -0.00 instead of x = 0.00. I have tried comparing like if(x==-0.00) x=fabs(x) but I've read that it won't work like that with doubles. So my question is are there any other ways to check if double is equal to negative zero?

5 Answers

You can use the standard macro signbit(arg) from math.h. It will return nonzero value if arg is negative and ​0​ otherwise.

From the man page:

signbit() is a generic macro which can work on all real floating- point types. It returns a nonzero value if the value of x has its sign bit set.

This is not the same as x < 0.0, because IEEE 754 floating point allows zero to be signed. The comparison -0.0 < 0.0 is false, but signbit(-0.0) will return a nonzero value.

NaNs and infinities have a sign bit.

Also, from cppreference.com:

This macro detects the sign bit of zeroes, infinities, and NaNs. Along with copysign, this macro is one of the only two portable ways to examine the sign of a NaN.

Very few calculations actually give you a signed negative zero. What you're probably observing is a negative value close to zero that has been truncated by your formatting choice when outputting the value.

Note that -0.0 is defined to be equal to 0.0, so a simple comparison to 0.0 is enough to verify a signed zero.

If you want to convert an exact signed zero -0.0 to 0.0 then add 0.0 to it.

Most likely, your program has a small negative value, not zero, which printf formats as “-0.00”. To print such numbers as “0.00”, you can test how printf will format them and replace the undesired string with the desired string:

#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");
}

This is portable. Alternatives such as comparing the number to -0.005 have portability issues, due to implementation-dependent details in floating-point formats and rounding methods in printf.

If you truly do want to test whether a number x is −0, you can use:

#include <math.h>
…
signbit(x) && x == 0

There are two functions you need here.

First, the signbit function can tell you if the sign bit is set on a floating point number. Second, the fpclassify function will tell you if a floating point number is some form of 0.

For example:

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));

Output:

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

So to check if a value is negative zero, do the following:

if (fpclassify(x) == FP_ZERO)) {
    if (signbit(x)) {
        printf("x is negative zero\n");
    } else {
        printf("x is positive zero\n");
    }
}

To always get the non-negative version, you don't need the comparison at all. You can take the absolute value all of the time. If the value is non-negative, fabs should return the original value.

Related