C 为什么该函数与float一起正常工作,但与';你不能和double一起工作吗?

C 为什么该函数与float一起正常工作,但与';你不能和double一起工作吗?,c,floating-point,double,bit-manipulation,C,Floating Point,Double,Bit Manipulation,我找到了检查浮点是否为2的幂的代码: int isPowOf2(float number) { union { float floatRepresent; int intRepresent; } bitset; bitset.floatRepresent = number; if((bitset.intRepresent & ((1 << 23)-1)) != 0) return

我找到了检查浮点是否为2的幂的代码:

int isPowOf2(float number) {
    union {
        float   floatRepresent;
        int     intRepresent;
    } bitset;

    bitset.floatRepresent = number;

    if((bitset.intRepresent & ((1 << 23)-1)) != 0)
        return ((bitset.intRepresent & (bitset.intRepresent-1)) == 0); // denormalized number
    int power = bitset.intRepresent >> 23;
    return power > 0 && power < 255;
}

// ...

printf("[%f -> %d] ",2.0,isPowOf2(2.0f)); // [2.000000 -> 1] 
printf("[%f -> %d] ",4.0,isPowOf2(4.0f)); // [4.000000 -> 1]
printf("[%f -> %d] ",0.25,isPowOf2(0.25f)); // [0.250000 -> 1]
printf("[%f -> %d]\n ",11.0,isPowOf2(11.0f)); // [11.000000 -> 0]
intispowo2(浮点数){
联合{
浮动代表;
int int代表;
}位集;
bitset.floatRepresentation=数字;
如果((bitset.int)表示&((1>23;
返回功率>0&&power<255;
}
// ...
printf(“[%f->%d]”,2.0,ispow2(2.0f));//[2.000000->1]
printf(“[%f->%d]”,4.0,ispowo2(4.0f));//[4.000000->1]
printf(“[%f->%d]”,0.25,ispow2(0.25f));//[0.250000->1]
printf(“[%f->%d]\n”,11.0,ispowo2(11.0f));//[11.000000->0]
正如您在评论中看到的,它可以正常工作。但当我尝试将此程序转换为双倍数字版本时,它会给出错误的结果:

int isPowOf2(double number) {
    union {
        double      floatRepresent;
        long long   intRepresent;
    } bitset;

    bitset.floatRepresent = number;

    if((bitset.intRepresent & ((1 << 53)-1)) != 0)
        return ((bitset.intRepresent & (bitset.intRepresent-1)) == 0); // denormalized number
    int power = bitset.intRepresent >> 53;
    return power > 0 && power < 2047;
}

// ...

printf("[%f -> %d] ",2.0,isPowOf2(2.0)); // [2.000000 -> 1] 
printf("[%f -> %d] ",4.0,isPowOf2(4.0)); // [4.000000 -> 0]
printf("[%f -> %d] ",0.25,isPowOf2(0.25)); // [0.250000 -> 0]
printf("[%f -> %d]\n ",11.0,isPowOf2(11.0)); // [11.000000 -> 0]
intispowo2(双倍数字){
联合{
双重浮动代表;
长时间的工作;
}位集;
bitset.floatRepresentation=数字;
如果((bitset.int)表示&((1>53;
返回功率>0&&power<2047;
}
// ...
printf(“[%f->%d]”,2.0,ispow2(2.0));//[2.000000->1]
printf(“[%f->%d]”,4.0,ispowo2(4.0));//[4.000000->0]
printf(“[%f->%d]”,0.25,ispow2(0.25));//[0.250000->0]
printf(“[%f->%d]\n”,11.0,ispowo2(11.0));//[11.000000->0]

您能解释一下是什么问题吗?

代码正在执行无效的移位。1是一个int。需要一个long


代码也不能正确使用+无穷大

// return power > 0 && power < 2047;
return power > 0 && power < 1023;  // Candidate fix for infinity.
//返回功率>0&&power<2047;
返回幂>0&&power<1023;//无穷大的候选修复。

代码正在执行无效的移位。
1
是一个
int
。需要一个
long


代码也不能正确使用+无穷大

// return power > 0 && power < 2047;
return power > 0 && power < 1023;  // Candidate fix for infinity.
//返回功率>0&&power<2047;
返回幂>0&&power<1023;//无穷大的候选修复。

故障原因是有效位中的位数错误

float的情况下
23位存储为24位

double
53的情况下,存储52位

纠正了这一点,并添加了
LL
限定符(如注释中所述),违规行变为

if((bitset.intRepresent & ((1LL << 52)-1)) != 0) {

if((bitset.intrepresentation&((1LL故障原因是有效位中的位数错误

float的情况下
23位存储为24位

double
53的情况下,存储52位

纠正了这一点,并添加了
LL
限定符(如注释中所述),违规行变为

if((bitset.intRepresent & ((1LL << 52)-1)) != 0) {

if((bitset.intrepresentation&)((1LL)不确定它是否重要,但在执行位操作时,您几乎应该始终使用
无符号的
。如果您的编译器具有
sizeof(int)==4
,然后
1这是定义的实现您需要提供什么是您的编译器什么是您的操作系统以及至少什么是您的处理器。@Someprogrammerdude
0.25
2^-2
@ntrsBIG不应该是
52
,而不是
53
?代码指存储的尾数位数,带有e前导(整数)位是隐式的。不确定这是否重要,但在执行位操作时,您几乎应该始终使用
无符号的
。如果您的编译器具有
sizeof(int)==4
,然后
1这是定义的实现您需要提供什么是您的编译器什么是您的操作系统以及至少什么是您的处理器。@Someprogrammerdude
0.25
2^-2
@ntrsBIG不应该是
52
,而不是
53
?代码指存储的尾数位数,带有e前导(整数)位是隐式的。