检测算术溢出(或算术下溢)并获得溢出计数的最合适方法是什么?
为了更容易理解,我将使用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
}