6

我希望 alwaysPositive 被分配一个正数,其中 lareValue1 和 largeValue2 的所有可能值(这些至少为 1)。

以下语句导致缓冲区溢出:

int alwaysPositive = (largeValue1 + largeValue2) / 2;

我知道我可以通过减去和添加来防止它:

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

但在其他编程语言中,我可以使用无符号位移位来解决问题:

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

我怎样才能在 C# 中做到这一点?


下面的答案都解决了这个问题。可能有很多方法可以做到这一点,但它们(包括我的解决方案)都有一个共同点:它们看起来都被混淆了。

4

6 回答 6

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

上面的想法是,如果您在添加结果之前预先划分结果,那么您将避免溢出,因为两个高位都将被取消设置。然后,如果两者都是正数(向下舍入),则添加一些轻微的校正逻辑以将值增加一。如果您只关心其中一个是否为正(四舍五入),那么您可以将其更改为

int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + ((largeValue1 | largeValue2) & 0x01);
于 2008-09-22T21:10:32.823 回答
3

unchecked((largeValue1 + largeValue2) >> 1)是另一种选择。

请参阅未选中关键字的文档。

于 2008-09-22T21:48:43.840 回答
2

你可以这样做:

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

这是一种获得两个整数的平均值而不会溢出的方法。

如果你愿意,你可以用位移替换除以二,但编译器无论如何都会为你做这件事。

于 2008-09-22T20:48:36.090 回答
0
try
{
    checked { alwaysPositive3 = (largeValue1 + largeValue2); }
}
catch (OverflowException ex)
{
   // Corrective logic
}
于 2008-09-22T21:38:27.920 回答
0

你可以使用单位:

uint alwaysPositive = (uint)(largeValue1 + largeValue2) / 2;
于 2008-09-22T20:45:25.023 回答
0

不是吹毛求疵,而是您的意思是“整数溢出”而不是“缓冲区溢出”。

我不知道 C#,所以可能有另一种方法,但你可以通过屏蔽最高位来模拟无符号移位: (x >> 1) & 0x80000000

于 2008-09-22T20:46:13.397 回答