检查算术溢出并获取溢出计数

本文关键字:溢出 获取 检查 | 更新日期: 2023-09-27 17:53:08

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

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

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

…通过抛出异常。

这是我现在使用的。

然而,我不太喜欢这个中的异常处理。异常通常是非常昂贵的,我想从一开始就避免它们。对我来说,这似乎是一个愚蠢的例外。是否有一些算术魔法我可以做,以检测这个前期?

检查算术溢出并获取溢出计数

我猜你可以检查当前值和最大值之间的差是否足够大,可以做加法:

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

反过来呢?

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)。它在乘法时没有任何用处。

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

这样怎么样?

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

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

if (byte.MinValue + 240 > 24)
{
    // handle underflow
}