2011-09-15 83 views
0

好吧我之前发生过这种情况,因为内存分配问题或错误寻址等变量随机更改数字,例如当您超出数组范围时。不过,我没有使用数组或指针或地址,所以我不知道为什么在执行这个循环后,突然发觉“指数”设定为0后等于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; 
} 
+1

我会在调试代码的过程中添加'cout <<'进度,因为我看不懂它。 – Blender

+2

这是否会产生错误的最小示例? – Beta

+2

经过288次迭代后,这就是*它*它将等于什么...... –

回答

2

使用调试器或IDE,设置监视/断点/断言对指数的值(例如​​

什么的X是float_i2f()调用了错误的值?指数是否会爆炸所有x或某些范围?

(你刚刚说x何时x = 0x80800000?你是否在指数上设置了一个手表并且在调试器中设置了该值?应该回答你的问题。检查0x807FFFFF我RKS,例如?)

+0

为了增加这一点,几乎没有什么突然发生。如果这是一个可重复的错误,那么你是在做同样的事情错误的时间。你需要记录或观察代码发生故障的情况。 – madmik3

+0

@ madmik3这正是我刚刚对他说的:)需要更多信息。 – smci

+0

基本上我说的是,当x = 0x80800000发生这种情况时,试图在visual studio中测试它,我之前使用gdb使用unix,老师给我们提供了一个测试用例程序。 – oorosco

0

我用Visual Studio自己试了一下,输入“10”,它似乎工作正常。

问:你能给我一个输入值“x”吗?

问:你在使用什么编译器?你在哪个平台上运行?

+1

指数++呢? – madmik3

+0

我相信我们使用gcc,我们在unix中“制作”它,然后在其上执行测试客户端。测试客户告诉我,如果我错了。它声称,在测试0x80800000它弄虚作假,我已经缩小到无法进步,因为一个被设置为0,并且指数被设置为288,因为一些神的潜在原因 – oorosco

+0

考虑寻找gdb来逐步通过代码。 http://www.unknownroad.com/rtfm/gdbtut/gdbuse.html – madmik3

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; 

} 
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; 
} 
+0

奇怪的格式是必要的类和什么不是。我不能直接使常量大于8位,我也不能在条件下使用“<”运算符。 – oorosco

+0

正在处理它,它可能是它溢出的A值,似乎我可能不得不为这种情况下检查条件。 – oorosco

+0

不能使常量大于8位?我希望你忘记这堂课教给你的任何东西 - 这个代码有很多可怕的做法,这使得它很难验证,并且不会比可维护的替代品***更快。 – Potatoswatter

0

变量exponent没有做任何神秘的事情。你每循环一次递增exponent,所以它最终会碰到你喜欢的任何数字。真正的问题是为什么当你认为它应该退出时你的循环没有退出?

您的环路条件取决于a。随着循环重复,尝试打印出a的连续值。在a达到1073741824之后,您是否注意到有什么有趣的事发生了?你有没有听说过类中的整数溢出?

0

只是处理其中“a”为负的情况下(或更好,验证您的输入,所以它永远不会变为负诠释他的第1名),你应该罚款:)

0

a溢出。 a*2==0a==1<<31,所以每次exponent%32==0,a==0和你循环,直到exponent==300

还有一些其他的问题,以及:

fraction计算关闭exponent>=24时。负向左移不会自动转变为正向右移。

生成分数的掩码也有点不对。前导位总是假设为1和尾数只有23位,所以对于x分数< 2^23应该是:当abs(x)>=1<<31(顺带导致

fraction = (~(((0x01)<< 31) >> 8)) & (x << (24 - (exponent + 1))); 

环路来计算exponent失败精确度损失,如果你不合适的话);考虑到隐含的1的循环在这里会更好。

相关问题