/*
* float_i2f - Return bit-level equivalent of expression (float) x
* Result is returned as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point values.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned float_i2f(int x) {
int sign = x & (1 << 31);
int minus = 1 << 31;
int exp = 31;
int bias = 127;
int frac;
if (!x)
return 0;
if (x == minus)
return minus | ((exp + bias) << 23);
if (sign)
x = ~x + 1;
while (!(x & minus))
{
x <<= 1;
exp -= 1;
}
frac = (((~minus) & x) >> 8);
if (x & 0x80 && ((frac & 1) ||((x & 0x7f) > 0)))
frac++;
return sign + ((exp + bias) << 23) + frac;
}
我在driver.pl上检查了此代码,该代码检查了答案的正确性。 但是我发现了一些奇怪的东西。
如果最后一个return语句变为
return sign | ((exp + bias) << 23) | frac;
它说这行不通,但是如果我将其更改为
return sign + ((exp + bias) << 23) + frac;
它正确了。
两个代码有什么区别?为什么第一个不起作用? 请帮助我:(
答案 0 :(得分:1)
大量出现此问题。考虑例如2 25 -1 = 33554431,其2的补码二进制表示为
00000001 11111111 11111111 11111111 // or --> 0 00000011 11111111111111111111111
找到指数后,代码将frac
评估为
frac = (((~minus) & x) >> 8); // --> 0 00000000 11111111111111111111111
但是它必须四舍五入,因此它可以执行
if (x & 0x80 && ((frac & 1) ||((x & 0x7f) > 0)))
frac++; // --> 0 00000001 00000000000000000000000
基本上我们有一个进位,我们应该增加指数,就像我们必须将999表示为1x10 3 而不是9.99x10 2 那样。现在您可以看到|
或+
之间的区别:
sign + ((exp + bias) << 23) + frac; // --> 0 10011000 00000000000000000000000
sign | ((exp + bias) << 23) | frac; // --> 0 10010111 00000000000000000000000