2008-09-22 26 views
5

我希望alwaysPositive能夠爲lareValue1和largeValue2(至少是1)分配一個包含所有可能值的正數。我可以使用無符號右移防止C#中的整數溢出嗎?

下面的語句導致緩衝區溢出:

int alwaysPositive = (largeValue1 + largeValue2)/2; 

我知道我可以阻止它通過減去並添加:

int alwaysPositive = largeValue1 + ((largeValue2 - largeValue1)/2); 

但在其他編程語言,我可以用一個無符號位位移做技巧:

int alwaysPositive3 = (largeValue1 + largeValue2) >>> 1; 

我該如何在C#中做到這一點?


下面的答案都解決了這個問題。可能有很多方法可以做到這一點,但它們(包括我的解決方案)都有一個共同點:它們都顯得模糊不清。

+0

原諒我的無知,但你爲什麼要這樣做呢? – 2008-09-22 20:53:05

+0

我試圖做到這一點的原因是重新發明輪子:實現二分查找。爲什麼我會寫我自己的版本?我不知道... – Paco 2008-09-22 21:43:39

+0

只是FYI,你的代碼示例做了不同的事情。我想你想在第一個括號。 PS。您的靈感來自http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html嗎? – 2008-09-23 01:14:51

回答

0

你可以使用的uint:

uint alwaysPositive = (uint)(largeValue1 + largeValue2)/2; 
+0

這仍然會溢出。增加溢出。 – 2008-09-22 21:14:32

0

不是雞蛋裏挑骨頭,但你的意思是「整數溢出」,而不是「緩衝區溢出」。

我不知道C#,所以有可能是另一種方式,但你可以通過只屏蔽掉頂位模仿一個無符號的轉變:(X >> 1)&爲0x80000000

2

你能做到這方式:

x = largeValue1; 
    y = largeValue2; 
    return (x&y)+((x^y)/2); 

這是一個有點迂迴的方式來獲得兩個整數的平均值沒有溢出。

如果你想要的話,你可以用一個位移來代替兩位,但是編譯器會爲你做到這一點。

3
int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + (largeValue1 & largeValue2 & 0x01); 

上述背後的想法是,你加他們面前,那麼你會避免溢出既是高序位將被取消設置,如果你預先劃分的結果。然後,如果兩者均爲正值(向下舍入),則添加一些輕微的校正邏輯以將值增加1。如果你只關心一方爲陽性(四捨五入),那麼你可以將其更改爲

int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + ((largeValue1 | largeValue2) & 0x01); 
0
try 
{ 
    checked { alwaysPositive3 = (largeValue1 + largeValue2); } 
} 
catch (OverflowException ex) 
{ 
    // Corrective logic 
} 
2

unchecked((largeValue1 + largeValue2) >> 1)是另一種選擇。

請參閱unchecked keyword的文檔。