好吧,我之前发生了这种情况,因为内存分配问题或错误的寻址等因素导致变量随机改变数字,例如当你超出数组范围时。但是,我没有使用数组,指针或地址,所以我不知道为什么在执行这个循环后它突然决定设置为0
后的“exponent”等于循环内的288
:
编辑:它决定专门打破:0x80800000
。
这在一次测试中没有中断,我们有一个“测试”客户端,它遍历几个测试用例,每次再次调用它时,每次再次调用该函数时,值应该是设置等于原始值。
/*
* 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= 0;
int a=0;
int exponent=0;
int crash_test=0;
int exp=0;
int fraction=0;
int counter=0;
if (x == 0) return 0;
if (!(x ^ (0x01 << 31)))
{
return 0xCF << 24;
}
if (x>>31)
{
sign = 0xFF << 31;
x = (~x) + 1;
}
else
{
sign = 0x00;
}
//printf(" After : %x ", x);
a = 1;
exponent = 0;
crash_test = 0;
while ((a*2) <= x)
{
if (a == 0) a =1;
if (a == 1) crash_test = exponent;
/*
if(exponent == 288)
{exponent =0;
counter ++;
if(counter <=2)
printf("WENT OVERBOARD WTF %d ORIGINAL %d", a, crash_test);
}
*/
if (exponent > 300) break;
exponent ++;
a *= 2;
}
exp = (exponent + 0x7F) << 23;
fraction = (~(((0x01)<< 31) >> 7)) & (x << (25 - (exponent + 1)));
return sign | exp | fraction;
}
答案 0 :(得分:2)
使用调试器或IDE,在指数值上设置监视/断点/断言(例如 (exponent > 100)
。
调用 float_i2f()
的x的违规值是多少?所有x或某个范围的指数是否爆炸?
(你刚才说x = 0x80800000吗?你是否设置了一个关于指数的监视并在调试器中为该值设置步骤?应该回答你的问题。例如,你检查了0x807FFFFF的工作原理吗?)
答案 1 :(得分:0)
我自己尝试使用Visual Studio,并输入“10”,它似乎工作正常。
问:在失败的情况下,你能给我一个“x”的输入值吗?
问:你用的是什么编译器?你在运行什么平台?答案 2 :(得分:0)
你的行在while循环结束时递增指数。
while((a*2) <= x)
{
if(a == 0) a =1;
if(a == 1) crash_test = exponent;
/*
if(exponent == 288)
{
exponent =0;
counter ++;
if(counter <=2)
printf("WENT OVERBOARD WTF %d ORIGINAL %d", a, crash_test);
}
*/
if(exponent > 300) break;
exponent ++;
a *= 2;
}
答案 3 :(得分:0)
在那里有很多无用的优化尝试,我已经删除了它们,因此代码更容易阅读。我也酌情使用了<stdint.h>
种类型。
循环中a *= 2
中有符号整数溢出,但主要问题是缺少常量和奇怪的魔数计算。
这仍然不是示例性的,因为常量应该都被命名,但这似乎可靠地起作用。
#include <stdio.h>
#include <stdint.h>
uint32_t float_i2f(int32_t x) {
uint32_t sign= 0;
uint32_t exponent=0;
uint32_t fraction=0;
if (x == 0) return 0;
if ( x == 0x80000000 )
{
return 0xCF000000u;
}
if ( x < 0 )
{
sign = 0x80000000u;
x = - x;
}
else
{
sign = 0;
}
/* Count order of magnitude, this will be excessive by 1. */
for ( exponent = 1; ( 1u << exponent ) <= x; ++ exponent ) ;
if ( exponent < 24 ) {
fraction = 0x007FFFFF & ( x << 24 - exponent ); /* strip leading 1-bit */
} else {
fraction = 0x007FFFFF & ( x >> exponent - 24 );
}
exponent = (exponent + 0x7E) << 23;
return sign | exponent | fraction;
}
答案 4 :(得分:0)
变量exponent
没有做任何神秘的事情。您每次循环都会递增exponent
,因此它最终会达到您喜欢的任何数字。真正的问题是为什么你的循环在你认为应该退出时不会退出?
您的循环条件取决于a
。尝试在循环重复时打印出a
的连续值。你注意到a
到达1073741824后发生了什么有趣的事吗?您是否听说过班级中的整数溢出?
答案 5 :(得分:0)
只需处理“a”变为负数的情况(或更好,验证您的输入,以便它在第一时间永远不会变为负数),您应该没问题:)
答案 6 :(得分:0)
a
溢出。 a*2==0
a==1<<31
,exponent%32==0
,每次a==0
,exponent==300
并循环到fraction
。
还有一些其他问题:
exponent>=24
时1
计算已关闭。负左移不会自动转为正向右移。
生成分数的掩码也略有错误。始终假定前导位为 fraction = (~(((0x01)<< 31) >> 8)) & (x << (24 - (exponent + 1)));
,并且尾数仅为23位,因此x <2 ^ 23的分数应为:
exponent
计算abs(x)>=1<<31
的循环在1
时失败(如果不适当地舍入,则偶然会导致精度损失);将隐式{{1}}考虑在内的循环在这里会更好。