2016-02-05 42 views
0

假设我想乘以x(3/8)。所以,我可以用移位操作如下结果(结果要圆接近零):处理分数乘法溢出

int Test(int x) { 
    int value = (x << 1) + x; 
    value = value >> 3; 
    value = value + ((x >> 31) & 1); 
    return value; 
} 

所以我会在Test(11)4-3Test(-9)。问题是,因为我第一次做乘法,我就必须在某个范围内溢出,并在这些情况下,我不会得到正确的值:

Test(0x80000000) // returns -268435455, but it should be -268435456 

我怎样才能解决这个问题?

+2

你已经在某天前发布了这个问题。我(和其他人)告诉你,调用_undefined_和_implementation定义的behaviour_。而溢出也会调用未定义的行为,所以所有投注都关闭。 – Olaf

+0

您或者需要使用比int大的变量,例如假设'long'在你的系统上有更多的位。或者你可以把'int'分成两个'int',每个都有一半的位数,然后进行数学运算。 – user3386109

+0

@ user3386109:'long'在POSIX64上只有更多的位,并不是真正的便携式。最好使用固定宽度类型。这些也具有明确的表示,因此有符号/无符号转换行为。 – Olaf

回答

2

我该如何解决这个问题? (在某些范围溢出)

先被8除。

对于8的每个倍数,结果精确地增加3。因此,剩下的就是找出数字-7到7中的3/8,OP的test()可以处理。简化可能。

int Times3_8(int x) { 
    int div8 = x/8; 
    int value = div8*3 + Test(x%8); 
} 
0

一个解决方案是以不同的方式处理高低两半。对于x的高半部分,先右移3,然后乘以3.对于下半部分,乘以3,然后右移3,然后将两个结果相加。这应该适用于积极的情况。对于负数,你需要稍微调整一下。

0
int foo(int x) 
{ 
    return x/8*3 + x%8*3/8; 
} 

http://ideone.com/2wGtpl

通过chux的回答的启发:关键是通过划分8第一(牺牲精度的范围),并使用第二项处理的量化误差(纠正小范围内的错误)。