2008-09-22 27 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的文档。