88

I had this weird experience with problem number 10 on Project Euler (great site by the way). The assignment was to calculate the sum of all the prime numbers below two million.

I used an int for the sum, and my algorith produced an answer, but when i pasted it to verify the answer, it was wrong.

It turned out that the result was too big to fit in an int, but wouldn't this cause an overflow error or something? Instead, it just returned a value far off from the real answer.

When I changed the type to long, everything was hunky dory.

3
  • 5
    Do you really want every integer operation to check for overflow? Commented Jan 13, 2010 at 12:11
  • 6
    Well, it shure would have saved me some time in this particular case ;) Commented Jan 13, 2010 at 12:18
  • 1
    In this case, yes. The vast majority of operations can't possibly overflow though. It would be interesting if the compiler could prove this and disable checking as a result, but I very much doubt it does. Commented Jan 13, 2010 at 12:34

6 Answers 6

117

C# integer operations don’t throw exceptions upon overflow by default. You can achieve that via the project settings, or by making the calculation checked:

int result = checked(largeInt + otherLargeInt);

Now the operation will throw.

The opposite is unchecked, which makes any operation explicitly unchecked. Obviously, this only makes sense when you’ve got checked operations enabled in the project settings.

Sign up to request clarification or add additional context in comments.

6 Comments

Unless you're in debug mode, where I think int operations are checked by default.
Nope. I ran in debug mode when this occured.
Oh. I stand corrected. I was sure that my Project Euler projects told me about overflows in debug mode. :/
"Obviously, this only makes sense when you’ve got checked operations enabled in the project settings." ... or you want to evaluate an unchecked expression in a checked context. You can certainly nest the blocks.
@NealDavis Inside a checked block or expression, an OverflowException is thrown. If you don’t care about overflows, don’t check for them. Your checksum example would be a typical use-case where you don’t want to check for overflows. This will normally roll around (not go to zero). However, note that C# (and other languages) by default do something cheeky called “integer promotion”. The result of adding two bytes is an integer. If you print that directly, the result may be larger than what can fit inside a byte. You need to reassign it to a byte (or cast it) to truncate it.
|
28

In C# an OverflowException is not thrown (in VB the exception is thrown per default).

To get the excpetion you have to embed your code in a checked context:

byte value = 241;
checked
{
    try 
    {
        sbyte newValue = (sbyte) value;
        Console.WriteLine("Converted the {0} value {1} to the {2} value {3}.", 
            value.GetType().Name, value, 
            newValue.GetType().Name, newValue);
    }
    catch (OverflowException) 
    {
        Console.WriteLine("Exception: {0} > {1}.", value, SByte.MaxValue);
    }
}       

MSDN explains in more detail:

For the arithmetic, casting, or conversion operation to throw an OverflowException, the operation must occur in a checked context. By default, arithmetic operations and overflows in Visual Basic are checked; in C#, they are not. If the operation occurs in an unchecked context, the result is truncated by discarding any high-order bits that do not fit into the destination type.

Comments

23

It's because, by default C# do not throw any exception for integer overflow as well as underflow. There are couple of things you can do here.

Option 1

You have to enable the exception to be thrown by go to Project => properties => Build tab => Advanced => check for arithmetic overflow underflow.(make sure you tick the option)

enter image description here

Make sure you tick the option

Option 2

Use a checked block and throw an overflow exception to handle the situation. A sample code snippet would be

        try
        {
            checked
            {
                int y = 1000000000;
                short x = (short)y;
            }
        }
        catch (OverflowException ex)
        {
            MessageBox.Show("Overflow");
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error");
        }

Comments

9

I have already added a comment, but maybe it would be interesting for some of you:

msdn tells us:

Integer arithmetic overflow either throws an OverflowException or discards the most significant bits of the result

but

Decimal arithmetic overflow always throws an OverflowException.

also

When integer overflow occurs, what happens depends on the execution context, which can be checked or unchecked. In a checked context, an OverflowException is thrown. In an unchecked context, the most significant bits of the result are discarded and execution continues. Thus, C# gives you the choice of handling or ignoring overflow.

1 Comment

Which makes sense, since decimals are mostly used for either currency or scientific calculations, and you would probably rather have them throw then fail silently.
6

By default, C# does not check for arithmetic overflow on integers. You can change this with the /checked compiler option or by enabling "Check for arithmetic overflow/underflow" in Visual Studio (project properties - Build - Advanced).

You can use checked and unchecked keywords to override the default on a case-by-case basis. If you rely on checking taking place in a piece of code, explicitly enabling it using checked would be a good idea.

int j = checked(i * 2);

checked
{
    int j = i * 2;
    // Do more stuff
}

Note that floating point operations never throw an OverflowException, and decimal operations always throw an OverflowException. See also C# operators.

Comments

1

You can set checked directly in csproj by adding:

  <PropertyGroup>
    <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
  </PropertyGroup>

It's the equivalent of ticking that Check for arithmetic overflow/underflow checkbox in the designer.

1 Comment

This is the only correct answer. I would also add: It can be done at the level of the individual project or at the level of some directory using Directory.Build.props. Also, you can do it only for some configurations, for example, for Debug. The answer based on Visual Studio is good but not yet sufficient because the development is not reduced to Visual Studio, so we need to know how things are done at the MSBuild level, to use other development tools correctly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.