简体   繁体   中英

right shifting the binary representation of the floating point number -0.0

I am doing a program to check the sign of a double/float number, first of all I cast the pointer of the number into a long int, then I check the sign bit if it's 0 or 1. I don't understand why the printing of the sign bit with this operation *pointer >> 63 is -1 instead of 1?(assuming *pointer is the int64_t that I casted my double/float into)

This is the entire code :

    double d = -0.0;
    int64_t *pointer = (int64_t *) &d;
    if (*pointer >> 63)
       printf("negative number\n");
    else
       printf("positive number\n");
    // if i print the result of (*pointer >> 63), it gives me -1
    // so how can this go inside my if condition?

By the way the binary printing of -0.0 in 64 bits gives me 100000000...000

This is hard to do in full generality due to the existence of signed zeros in floating point types, and the possibility of 1's complement integral types.

Aside from the undefinedness of (int64_t*)&d (which you could address with a union type-pun), that approach will return the wrong sign for -0.0 .

Fortunately you can use signbit() from math.h that probably implements the function in a non-portable manner.

First, right shifting a negative integer is implementation defined. Next dereferencing a pointer of a type different from the actual type is explicitely undefined behaviour because of the strict aliasing rule (google for it it you do not know it).

If you want your code to be portable, the only foolproof way is to use memcpy to transport the representation of the value. This only assumes that:

  • sizeof(double) is the same as sizeof(uint64_t) :
  • the sign bit is bit63 of an uint64_t having that representation

Code:

double d = -0.0;
uint64_t u;

memcpy(&u, &d, sizeof(u));

print("Sign bit in that architecture %d\n", u>>63); 

so how can this go inside my if condition?

1 Use signbit(d)

if (signbit(d)) {
  puts("Negative");
}

or

2 Use a compound literal and union .

//  v--------------------------------------------v  compound literal
if ((union { double dd; int64_t i64; }){ .dd = d }.i64 < 0) {
  puts("Negative");
}

This approach needs to have the expected size, and a double encoding with the sign bit in the same place as int64_t .

// Test size
_Static_assert(sizeof(int64_t) == sizeof(double), "Mis-match size");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM