简体   繁体   English

右移浮点数的二进制表示形式-0.0

[英]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) 我正在执行一个程序来检查双精度或浮点数字的符号,首先,我将数字的指针转换为长整型,然后检查符号位是否为0或1。我不明白为什么通过此操作打印符号位* pointer >> 63是-1而不是1?(假设* pointer是我将double / float转换为的int64_t)

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 顺便说一句-0.0以64位二进制打印给我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. 由于浮点类型中存在有符号的零,并且存在1的补码整数类型的可能性,因此很难完全笼统地做到这一点。

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 . 除了(int64_t*)&d的不(int64_t*)&d (您可以使用union type-pun来解决)之外,该方法还会为-0.0返回错误的符号。

Fortunately you can use signbit() from math.h that probably implements the function in a non-portable manner. 幸运的是,您可以使用math.h中的signbit() ,它可能以非便携式的方式实现了该功能。

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). 接下来,由于严格的别名规则(对于Google,您不知道),因此取消引用与实际类型不同的类型的指针显然是未定义的行为。

If you want your code to be portable, the only foolproof way is to use memcpy to transport the representation of the value. 如果您希望代码具有可移植性,那么唯一安全的方法就是使用memcpy传输值的表示形式。 This only assumes that: 这仅假设:

  • sizeof(double) is the same as sizeof(uint64_t) : sizeof(double)sizeof(uint64_t)相同:
  • the sign bit is bit63 of an uint64_t having that representation 符号位是具有该表示形式的uint64_t bit63

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? 那么这怎么能进入我的if条件呢?

1 Use signbit(d) 1使用signbit(d)

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

or 要么

2 Use a compound literal and union . 2。使用复合文字和并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 . 这种方法需要具有预期的大小,并且必须使用与int64_t相同的符号位进行double编码。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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