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

时间:2019-05-16 12:58:10

标签: c floating-point double bit-manipulation

我正在执行一个程序来检查双精度或浮点数字的符号,首先,我将数字的指针转换为长整数,然后检查符号位是否为0或1。我没有理解为什么使用此操作* pointer >> 63来打印符号位是-1而不是1?(假设* pointer是我将double / float强制转换为的int64_t)

这是完整的代码:

    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?

通过-0.0的64位二进制打印,我得到了100000000 ... 000

3 个答案:

答案 0 :(得分:3)

由于浮点类型中存在带符号的零以及可能存在1的补码整数类型,因此很难完全通用。

除了(int64_t*)&d的不确定性(您可以使用union类型双关来解决)之外,该方法还会为-0.0返回错误的符号。

幸运的是,您可以使用signbit()中的math.h,它可能以非便携式的方式实现了该功能。

答案 1 :(得分:0)

首先,定义负整数右移。接下来,由于严格的别名规则(对于Google,您不知道),因此取消引用与实际类型不同的类型的指针显然是未定义的行为。

如果您希望代码具有可移植性,那么唯一安全的方法就是使用memcpy来传输值的表示形式。这仅假设:

  • sizeof(double)sizeof(uint64_t)相同:
  • 符号位是具有该表示形式的uint64_t的bit63

代码:

double d = -0.0;
uint64_t u;

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

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

答案 2 :(得分:0)

  

那么这如何进入我的if条件中?

1使用signbit(d)

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

2使用复合文字和union

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

此方法需要具有预期的大小,并且必须使用double进行编码,且符号位应与int64_t放在同一位置。

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