C# 检查算术溢出并获取溢出计数?

C# 检查算术溢出并获取溢出计数?,c#,exception,math,integer-overflow,integer-arithmetic,C#,Exception,Math,Integer Overflow,Integer Arithmetic,检测算术溢出(或下溢)并获取溢出计数的最合适方法是什么 为了便于理解,我将使用byte,但int或任何其他基本整数类型也是如此。现在想象一下,我有240的值,并想加上24。显然是算术溢出。使用checked关键字,这至少很容易检测到 byte value = 240; try { checked { value += 24; } } catch (OverflowException e) { // handle overflow, get over

检测算术溢出(或下溢)并获取溢出计数的最合适方法是什么

为了便于理解,我将使用
byte
,但
int
或任何其他基本整数类型也是如此。现在想象一下,我有240的值,并想加上24。显然是算术溢出。使用
checked
关键字,这至少很容易检测到

byte value = 240;
try
{
    checked
    {
        value += 24;
    }
}
catch (OverflowException e)
{
    // handle overflow, get overflow count via % etc.
}
。。。通过抛出异常

这就是我目前正在使用的


但是,我不太喜欢这一个中的异常处理。例外情况通常非常昂贵,我希望从一开始就避免它们。对我来说,这似乎是一个好消息我可以做一些算术运算来预先检测这个问题吗?

像这样的事情怎么样

if (byte.MaxValue - 240 < 24)
{
    // handle overflow
}

我想您可以检查当前值和最大值之间的差值是否足够大,以便进行加法:

var difference = byte.MaxValue - value;

if(difference >= 24)//OK to add 24
else//will cause overflow
要检测下溢,可以使用
byte.MinValue
值:

var difference = value - byte.MinValue;
if(difference >= 24)//OK to subtract 24
else//will cause underflow

考虑到这些,您甚至可以为它们制作一些扩展方法:

public static class OverflowExtensions
{
    public static bool WillAdditionOverflow(this byte b, int val)
    {
        return byte.MaxValue - b < val;
    }

    public static bool WillSubtractionUnderflow(this byte b, int val)
    {
        return b - byte.MinValue < val;
    }
}

换个方向做怎么样

byte oldValue = 240;
byte newValue;

unchecked
{
  newValue = (byte)((oldValue + 24) % 255);
}

// if (newValue < oldValue), overflow happened and newValue 
// contains the "amount" of overflow
字节oldValue=240;
字节新值;
未经检查
{
新值=(字节)((旧值+24)%255);
}
//如果(newValue
(字节上需要
%255
,因为
byte+byte
是一个整数,可能是出于可移植性的原因)

请注意,只有当您要添加的数字与值大小相同(即,两者都是字节,都是整数…)且仅适用于添加时,此选项才有效。对于减法,只需反转比较(
newValue>oldValue
)。它在乘法时没有任何用处


这种方法的优点是它不依赖于数据类型足够大而不会首先导致溢出,这是建议的其他一些方法的一个缺点。

如果我错了,请纠正我,但这不会检测到下溢,或者是吗?对。您必须为下溢编写类似的检查。
using MyApp.OverflowExtensions;
//...

if(value.WillAdditionOverflow(24))
    //value + 24 will cause overflow

if(value.WillSubtractionUnderflow(24))
    //value - 24 will cause underflow
byte oldValue = 240;
byte newValue;

unchecked
{
  newValue = (byte)((oldValue + 24) % 255);
}

// if (newValue < oldValue), overflow happened and newValue 
// contains the "amount" of overflow