为什么这两个代码给出不同的输出? // bits.c float_i2f
Why are these two codes giving a different output? // bits.c float_i2f
/*
* 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;
它变得正确。
两种代码有什么区别?为什么第一个不起作用?
请帮助我:(
问题随着数字的增加而增加。考虑例如 225 - 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 表示为 1x103 而不是 9.99x102 一样。现在您可以看到 |
或 +
之间的区别:
sign + ((exp + bias) << 23) + frac; // --> 0 10011000 00000000000000000000000
sign | ((exp + bias) << 23) | frac; // --> 0 10010111 00000000000000000000000
/*
* 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;
它变得正确。
两种代码有什么区别?为什么第一个不起作用? 请帮助我:(
问题随着数字的增加而增加。考虑例如 225 - 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 表示为 1x103 而不是 9.99x102 一样。现在您可以看到 |
或 +
之间的区别:
sign + ((exp + bias) << 23) + frac; // --> 0 10011000 00000000000000000000000
sign | ((exp + bias) << 23) | frac; // --> 0 10010111 00000000000000000000000