如何在C中使用逐位和逻辑运算符将无符号数转换四倍

目标:

4x ( 4.400000095 ) = 17.60000038 
  • 合法操作:任何整数/未签名操作,包括。 ||,&&。 如果,同时
  • Max ops:30
  • 返回表达式x + x + x + x的位级等价物
  • 浮点参数f。

我的代码:

 unsigned 4x(unsigned uf) { unsigned expn = (uf >> 23) & 0xFF; unsigned sign = uf & 0x80000000; unsigned frac = uf & 0x007FFFFF; if (expn == 255 || (expn == 0 && frac == 0)) return uf; if (expn) { expn <> 2; expn << 2; } else { frac <<= 2; } return (sign) | (expn << 23) | (frac); 

}

你可以猜到,我的代码不起作用。 输入加倍,而不是输入翻两番。 我不知道为什么因为分数和指数总是右移/左移2而不是1.我在32位机器中使用单精度浮点值。

一些未经测试的代码 – 留给OP。 (GTG)

棘手的一点是处理* 4变为正常时的子正常数。 还要注意溢出到无穷大的大值。 如果你想忽略子法线,只需要expn += 2并检查溢出。

对于正常数字,另一种方法将expn += 2 。 对于子法线,移动frac <<= 2并处理变为正常的情况。

代码大约是30个操作。

 #include  float x4(float x) { // Use union to access the bits. Leap-of-faith here (float is 32 bits, endian) union { float f; uint32_t u32; } u; uf = x; uint32_t expn = (u.u32 >> 23) & 0xFF; uint32_t sign = u.u32 & 0x80000000; uint32_t frac = u.u32 & 0x007FFFFF; // Nan Inf if (expn == 255) return uf; if (expn == 0) { expn++; // Bring sub-normal into normal expo range } else { frac += 0x800000; // restore implied bit } // *4 frac <<= 2; // normalize - this usually iterates twice, less for sub-normals while (frac > 0xFFFFFF) { expn++; frac >>= 1; // 1's will not be shifted out as 2 LSB are 0 so no later rounding } // overflow to inf if (expn >= 255) { expn = 255; frac = 0; } else if (frac & 0x800000) { frac ^= 0x800000; // clear implied bit } else { // still sub-normal expn--; // should now be 0 } u.u32 = sign | (expn << 23) | frac; return uf; } 

注意

 expn << 2; 

不修改expn 。 你可能想要

 expn <<= 2; 

同上

 frac >> 2; expn << 2; 

但是,正如@chux指出的那样,你只需要增加指数的加2,而不是将指数乘以4。