3

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

为了更容易理解,我将使用byte,但这对于int任何其他基本整数类型都是相同的。现在想象一下我的值是 240 并且想给它加上 24。显然是算术溢出。使用checked关键字这至少很容易检测到......

byte value = 240;
try
{
    checked
    {
        value += 24;
    }
}
catch (OverflowException e)
{
    // handle overflow, get overflow count via % etc.
}

...通过抛出异常。

这就是我目前正在使用的。

但是,我不太喜欢这个中的异常处理。异常通常非常昂贵,我想从一开始就避免它们。对我来说,这似乎是一个Boneheaded-Exception无论如何。我可以做一些算术魔法来预先检测到这个吗?

4

3 回答 3

3

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

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;
    }
}

您可以像这样使用它:

using MyApp.OverflowExtensions;
//...

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

if(value.WillSubtractionUnderflow(24))
    //value - 24 will cause underflow
于 2014-03-24T14:40:46.817 回答
2

这样的事情怎么样?

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

对于下溢,比如说,看看你是否可以做 24 - 240

if (byte.MinValue + 240 > 24)
{
    // handle underflow
}
于 2014-03-24T14:40:38.877 回答
2

反过来做呢?

byte oldValue = 240;
byte newValue;

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

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

% 255字节需要,因为byte + byte它是一个整数,可能是出于可移植性的原因)

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

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

于 2014-03-24T14:48:24.053 回答