我可以使用无符号右移来防止 C# 中的整数溢出吗?

发布于 2024-07-05 16:53:02 字数 530 浏览 9 评论 0原文

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

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

int alwaysPositive = (largeValue1 + largeValue2) / 2;

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

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

但在其他编程语言中,我可以使用无符号位移来实现这一点:

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

如何在 C# 中做到这一点?


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

I want alwaysPositive to be assigned a positive number with all possible values for lareValue1 and largeValue2 (these are at least 1).

The following statement causes a buffer overflow:

int alwaysPositive = (largeValue1 + largeValue2) / 2;

I know I can prevent it by substracting and adding:

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

But in other programming languages I can use an unsigned bitshift to do the trick:

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

How can I do this in C#?


The answers below all solve the problem. There are probably lots of ways to do this, but they all (including my solutions) have one thing in common: they all look obfuscated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冰雪之触 2024-07-12 16:53:02

你可以这样做:

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

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

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

You can do it this way:

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

That's a bit-twiddling way to get the average of two integers without overflow.

If you want you can replace the division by two with a bit-shift, but the compiler will do that for you anyways.

梦中楼上月下 2024-07-12 16:53:02

您可以使用单位:

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

You could use uints:

uint alwaysPositive = (uint)(largeValue1 + largeValue2) / 2;
丑疤怪 2024-07-12 16:53:02
int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + (largeValue1 & largeValue2 & 0x01);

上述背后的想法是,如果在相加之前对结果进行预除,那么您将避免溢出,因为两个高位都将被重置。 然后,如果两者均为正值(向下舍入),则添加一些轻微的修正逻辑,将值增加 1。 如果您只关心其中一个是否为正(四舍五入),那么您可以将其更改为

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

The idea behind the above is that if you pre-divide the results before you add them, then you will avoid the overflow as both high-order bits will be unset. You then add some slight correction logic to increase the value by one if both were positive (round down). If you only care if either one was positive (round off) then you could change it to

int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + ((largeValue1 | largeValue2) & 0x01);
紧拥背影 2024-07-12 16:53:02

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

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

unchecked((largeValue1 + largeValue2) >> 1) is another option.

See the documentation for the unchecked keyword.

如果没有你 2024-07-12 16:53:02

不是挑剔,但你的意思是“整数溢出”而不是“缓冲区溢出”。

我不懂 C#,所以可能还有另一种方法,但您可以通过屏蔽顶部位来模拟无符号移位: (x >> 1) & 0x80000000

Not to nitpick, but you mean "integer overflow" rather than "buffer overflow".

I don't know C#, so there may be another way, but you could mimic an unsigned shift by just masking off the top bit: (x >> 1) & 0x80000000

遗失的美好 2024-07-12 16:53:02
try
{
    checked { alwaysPositive3 = (largeValue1 + largeValue2); }
}
catch (OverflowException ex)
{
   // Corrective logic
}
try
{
    checked { alwaysPositive3 = (largeValue1 + largeValue2); }
}
catch (OverflowException ex)
{
   // Corrective logic
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文