Question

What would be the most appropriate way to detect an arithmetic overflow (or underflow for that matter) and get the overflow count?

For easier understanding I'll will be using byte, but this is the same for int or any other basic integer type. Now imagine I have the value 240 and want to add 24 to it. Clearly an arithmetic overflow. Using the checked keyword this is easy to detect at least ...

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

... by throwing an exception.

This is what I am using at the moment.

However, I don't quite like the exception handling in this one. Exceptions are usually pretty expensive, and I want to avoid them right from the start. To me this seems like a Boneheaded-Exception anyways. Is there some arithmetic wizardry I could do to detect this upfront?

Was it helpful?

Solution

I guess you could check if the difference between the current value and the maximum if large enough to do the addition:

var difference = byte.MaxValue - value;

if(difference >= 24)//OK to add 24
else//will cause overflow

To detect underflows you can use the byte.MinValue value instead:

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

With these in mind you could go as far as making some extension methods for them:

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

Which you can use like so:

using MyApp.OverflowExtensions;
//...

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

if(value.WillSubtractionUnderflow(24))
    //value - 24 will cause underflow

OTHER TIPS

What about doing this the other way around?

byte oldValue = 240;
byte newValue;

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

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

(the % 255 is needed on byte, since byte + byte is an integer, perhaps for portability reasons)

Note that this only works if the number you're adding is the same size as the value (ie. both are bytes, both are ints...) and it only works for adding. For subtracting, you'd simply invert the comparison (newValue > oldValue). It isn't of any use when multiplicating.

The pro of this method is that it doesn't depend on having a data type big enough not to cause overflow in the first place, which is a weakness of some of the other methods suggested.

How about something like this?

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

For underflow to, say, see if you can do 24 - 240

if (byte.MinValue + 240 > 24)
{
    // handle underflow
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top