2016-02-05 52 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第一(犧牲精度的範圍),並使用第二項處理的量化誤差(糾正小範圍內的錯誤)。