14,981,770 members
Articles / Programming Languages / C#
Article
Posted 4 May 2016

31.8K views
13 bookmarked

# Arithmetic Overflow in .NET - Some Nitty Gritties

Rate me:
Let's get into few nitty gritties involved with integer data type and what can go wrong behind the scenes when its arithmetic limits are exceeded

## Introduction

This article will take you through a small journey related to basics of arithmetic overflow and underflow related to integer and long data types of .NET Framework. Knowledge of these few key details related to arithmetic overflow and underflow can save you a great deal of frustration and silent failures. Let's get started.

## Prerequisites

A basic knowledge of C# language and .NET Framework from Microsoft is desired while reading this article.

## A Note for Attached Code

You will need the following software to run the attached code on your computer:

1. Visual Studio 2012 or above

## Background

The idea for this article struck my mind when I was solving a very trivial problem given by a very good programmer friend of mine at my office. The problem was to print the successor of highest number which can be contained by integer (alias `Int32`) data type in .NET Framework. What followed through were a series of surprises.

## Basic Fundamentals

We will be dealing with only `Integer` data type in this article, but it is equally applicable to `long` data type as well without any deviation.

Note: Throughout my article, I've used `int`, `Integer` and `Int32` interchangeably. `int` is a keyword facility provided by C# compiler to integer data type as it is a primitive data type. So writing `int`, `Int32` and `System.Int32` in code is equivalent. For `System.Int64` data type, the keyword is `long`.

Let's quickly answer few basic questions which might be popping up in your mind right now:

What is an integer data type? `Int32` or `int` or `System.Int32` is a data type supported by .NET Framework to deal with computation of numbers. It can only contain integral values like `0``1`, `2`, `-1`,`-2`,`-3`. No fractional numbers can be stored in a variable of integer data type. Even if you attempt to do so, the fractional part will get automatically truncated. Internally, it has memory storage size of 32 bits as is evident from its name `Int32`. The highest possible value which a variable of type `Int32` can contain is `2147483647` and the lowest possible value is `-2147483648`.

What is arithmetic overflow? If you try assigning an integral value to a variable of type `integer` which is outside the range which spans between `-2147483648` and `2147483647`, it results in an arithmetic overflow error. Whenever the value being assigned to an integer variable is greater than `2147483647` or is less than `-2147483648`, then the resulting value along with its sign (+/-) can not be accomodated in the 32 bit memory space assigned to the variable which results in memory overflow.

.NET Framework class library has a built-in exception class named `System.ArithmeticException` to catch this overflow condition arising in code.

Here is a code snippet from the attached source code which generates `ArithemticException`. Here, the exception gets raised because of arithmetic overflow happening towards negative limit of Int32 data type.

#### Code Snippet # 1

C#
```        //Trivial code has been removed for brevity and clarity.
private static void CreateArithmeticOverflowForInteger()
{
try
{
var myNumber = int.MinValue;
var predecessorNumber = myNumber - 1;
}
catch (ArithmeticException ex)
{
Console.WriteLine(ex.ToString());
}

}```

## Using the Code

Getting back to my original problem statement of printing the successor of highest number which can be contained by integer data type, here is the program I wrote:

#### Code Snippet # 2

C#
```//Trivial code has been removed for brevity and clarity.

static void Main(string[] args)
{
PrintSuccessor(int.MaxValue);
}

private static void PrintSuccessor(int number)
{
Console.WriteLine(number + 1);
}
```

Here is what got printed on console: `-2147483648`

Highest value which can be stored by `Int32` data type is `2147483647`. The number which got printed here is `-2147483648`. What's going on in here? There is something wrong for sure as mathematically successor of `2147483647` (the highest value which can be stored in `Int32` data type) is `2147483648`. Also, if you noticed this value which got printed on console is actually the lowest possible integer which can be stored in `Int32` data type. Not to worry, all this is happening because of a C# project setting which is not enabled by default and results in this aberration. Let's check that.

## Project Setting to Escape Arithmetic Exceptions

Open solution explorer. Right click on the project file "`ArithmeticCalculationsNumericDataTypes`". Click properties in context menu. This will open the project properties window. You can also open this window by simply pressing alt + Enter after selecting project file in solution explorer. Now go to build tab in project properties window. Click Advanced button. Verify the value of "Check for arithmetic overflow/underflow" check box. Currently, it will be in unchecked state as shown below:

Now this particular setting being unchecked is the root cause of the aberrant behavior you are observing currently. This project setting instructs the compiler to generate MSIL which will ignore the arithmetic overflow exception. The moment you increase the value of an integer variable which goes past the positive limit of `Int32` data type, the value does a roll-over and gets set to negative limit of `Int32` data type which is `-2147483648`. No run time exceptions will be raised at all. Just a silent failure which no one can notice. :) I sent this source code to my friend only to face embarrassment as it was producing wrong result.

An irritating limitation: Once set in project properties, I've no way to change this behavior of arithmetic overflow at run time. If this setting is checked in project properties, it will always throw exception when arithmetic overflow occurs. If this setting is unchecked in project properties, it will always eat the exception when arithmetic overflow occurs and silently roll over to lower limit or upper limit of the data type as the case may be. What is the way out? C# compiler designers are smart people. :) Let's see what they have in store for us.

## Checked and Unchecked Programming Constructs

To modify/control the behavior of arithmetic overflow at run time, C# provides two programming constructs namely `checked` and `unchecked` keywords. Let's see them in action. Let's say at run time, you decide to enable arithmetic overflow exception. Here is a quick snippet which shows how it works:

C#
```//Trivial code has been removed for brevity and clarity.
private static void CheckedProgrammingConstruct()
{
checked
{
var myNumber = int.MaxValue;
//Exception will be raised here as we are inside checked block
var successorNumber = myNumber + 1;
}
}
```

So you can see clearly that in the last line, arithmetic overflow will happen. It will result in arithmetic exception as it is crossing the upper limit of `Int32` data type irrespective of the state of the arithmetic overflow setting in your project properties since this code block is enclosed inside `checked` block.

Let us now see `unchecked` programming construct:

C#
```//Trivial code has been removed for brevity and clarity.
private static void UncheckedProgrammingConstruct()
{
unchecked
{
var myNumber = int.MaxValue;
//Exception will NOT be raised here as we are inside unchecked block
var successorNumber = myNumber + 1;
}
}
```

So as you can see again in the last line of code, there is a likelihood of arithmetic overflow, but it will NOT result in any kind of arithmetic exception even if it is crossing the upper limit of `Int32` data type. It will silently jump to the negative limit of `Int32` data type irrespective of the state of the arithmetic overflow setting in your project properties since this code block is enclosed inside `unchecked` block.

## Who Solves My Successor Problem?

The only way to get the right result is to use the `Int64` (`long`) data type instead of `Int32` (`int`) data type. Here is the code which solves my friend's original problem:

C#
```//Trivial code has been removed for brevity and clarity.

static void Main(string[] args)
{
PrintSuccessorWithoutError(int.MaxValue);
}

private static void PrintSuccessorWithoutError(long number)
{
Console.WriteLine(number + 1);
}
```

## Do FCL Classes Respect Your Project Settings?

This is the MOST important take away for you which is why I wrote this article as this finding had left me in a bit of amazement and gave me food for thought. Let's say you have kept the "Check for arithmetic overflow/underflow" setting unchecked in your project properties. Now how the following code snippet will behave. `List<int>` is a framework class library (FCL) class which comes with .NET Framework. Here, we store two integers in a list and then ask the `Sum` API of `List<int>` class to sum them up. I've chosen two numbers in such a way that the summation process will result in an arithmetic overflow.

C#
```//Trivial code has been removed for brevity and clarity.
private static void BehaviorOfFclClasses()
{
var listOfNumbers = new List<int>();
//This sum operation is done by the FCL class internally and returned back to you.
var totalSumOfListItems = listOfNumbers.Sum();
}
```

This code results in arithmetic overflow exception irrespective of arithmetic overflow settings in project properties. This really goes in programmer's favor. The thing is it can get really chaotic if framework class libraries start eating arithmetic overflow exception under the carpet based on your project settings. If it starts happening, then they will return results like `sum` in this case which will be incorrect without throwing exception. So FCL classes always use `checked` keyword in their implementation wherever an arithmetic operation in involved. So don't feel dumbfounded next time if you see FCL classes not respecting your project settings for arithmetic overflow. :) They are doing it in your best interest.

So you are all set to dive into the world of arithmetic operations.

### Recommendations

1. Always follow the default project setting for arithmetic flow (Unchecked state). Enabling arithmetic overflow checks across the application in one shot using the project setting will have negative impact on performance. If you have specific cases where you feel you have to enable it, then do it through `checked` keyword in specific piece of code only at run time.

## Points of Interest

• I've an `Int32` variable. Let's say I assign it the lowest possible value of `Int32` data type. Now you have to think what arithmetic operation on the variable will cause the lower limit of `Int32` data type to jump to upper limit of `Int32` data type if the project setting I mentioned in this article is unchecked.
• How about putting an FCL class API which does arithmetic calculation enclosed inside `unchecked` keyword. Observe its behavior. Will it throw an arithmetic exception or eat it silently?
C#
``` unchecked

{
var listOfNumbers = new List<int>();
//This sum operation is done by the FCL class internally and returned back to you.
var totalSumOfListItems = listOfNumbers.Sum();
}
```

## History

• May 5, 2016 - First release
• May 9, 2016 - Updated the article to remove the concept of underflow. The concept of underflow is not related to integer data type. Integers always overflow both on their positive and negative limits.

## Share

 Software Developer 1E India
My professional details will hardly make a difference to you if you have come to know about me after reading my lengthy article but my intent will make a difference for sure. Why I write articles is for the sole motto which I got to know pretty late in my career. My motto is that there is ONLY one way of enhancing knowledge and that way is sharing. Blogs, articles and white papers are nothing but a form of knowledge sharing. It also helps you creating a backup copy of the knowledge you have in your brain and nerves. This backup copy will surely outlive your life as this knowledge gets transferred to uncountable people through sharing. So start contributing now! Always remember my favorite quote - "Knowledge is the ONLY antidote to all fears. Start reading a new book today". Don't seek Nirvana. Seek knowledge. Nirvana and knowledge are synonymous.

 First Prev Next
 Checked and Unchecked in VB BrianAtSyston3-Nov-19 3:14 BrianAtSyston 3-Nov-19 3:14
 Hey, that's nice one Ajay Vijayvargiya8-May-16 19:46 Ajay Vijayvargiya 8-May-16 19:46
 Re: Hey, that's nice one irneb10-May-16 3:01 irneb 10-May-16 3:01
 [My vote of 2] This is NOT what Underflow is Mark I6-May-16 2:14 Mark I 6-May-16 2:14
 Re: [My vote of 2] This is NOT what Underflow is Rasik Bihari Tiwari6-May-16 4:49 Rasik Bihari Tiwari 6-May-16 4:49
 Re: [My vote of 2] This is NOT what Underflow is Rasik Bihari Tiwari8-May-16 19:23 Rasik Bihari Tiwari 8-May-16 19:23
 Is there a big performance hit: DavidSherwood5-May-16 6:45 DavidSherwood 5-May-16 6:45
 Re: Is there a big performance hit: Rasik Bihari Tiwari5-May-16 11:47 Rasik Bihari Tiwari 5-May-16 11:47
 Re: Is there a big performance hit: Dmitriy Gakh10-May-16 0:16 Dmitriy Gakh 10-May-16 0:16
 32 Bytes? Rauhotz5-May-16 0:39 Rauhotz 5-May-16 0:39
 Re: 32 Bytes? Rasik Bihari Tiwari5-May-16 2:18 Rasik Bihari Tiwari 5-May-16 2:18
 Is that mean that programmer should know basic platform conceptions ? Dmitriy Gakh4-May-16 20:21 Dmitriy Gakh 4-May-16 20:21
 Re: Is that mean that programmer should know basic platform conceptions ? Rasik Bihari Tiwari4-May-16 21:04 Rasik Bihari Tiwari 4-May-16 21:04
 Thank you for your detailed feedback. I was really wondering why C# team has kept this option unchecked by default but was lazy to search for the reason. Now I'm getting that it has a performance impact in arithmetic computation. Agree with you opposing my recommendations. I got a link here which supports your view [here](math - Why doesn't C# use arithmetic overflow checking by default? - Stack Overflow[^])
 Re: Is that mean that programmer should know basic platform conceptions ? Dmitriy Gakh4-May-16 21:17 Dmitriy Gakh 4-May-16 21:17
 Re: Is that mean that programmer should know basic platform conceptions ? Rasik Bihari Tiwari5-May-16 0:01 Rasik Bihari Tiwari 5-May-16 0:01
 Last Visit: 31-Dec-99 18:00     Last Update: 3-Aug-21 12:12 Refresh 1