Numeric Overflow management in C#, Java, JavaScript and Python

Aniello Musella - Oct 25 '22 - - Dev Community

Do you now what happens when you increment by one the maximum value of a number?

The most common and logic answer: I get a Numeric Overflow Exception!

But the real answer is not always or probably never!

If you don't know how your compiler manage this kind of situation you could design bad algorithms with wrong solutions.

Let's prove that!

C#

In C# when you increment a max value you don't get a numeric overflow exception (this is a default behavior). Take a look to the following snippet, where the max integer value (2147483647) is incremented by one.

int count=int.MaxValue;
Console.WriteLine($"count is {++count}");
Enter fullscreen mode Exit fullscreen mode

in this case the output will be -2147483648 that is clearly an overflow because we get a negative number after an increment of positive number.This happens because the increment rises the most significant bit of the number, the sign bit (+/-).

To trigger an overflow/underflow exception we need to put the operation in a checked block like this:

int count = int.MaxValue;
checked
{
    Console.WriteLine($"count is {++count}");
}
Enter fullscreen mode Exit fullscreen mode

Here we go, the exception is served!
'System.OverflowException' in overflow-dotnet.dll: 'Arithmetic operation resulted in an overflow.'

In C# compiler you can enable the option CheckForOverflowUnderflow where the default context is a checked context and overflow checking is enabled (and complementary you can use the keyword unchecked to uncheck the context).

Java

In Java the behavior is very similar to what happens in C#, take a look to the following snippet!

Integer count=Integer.MAX_VALUE; // 2147483647
System.out.println(String.format("count is %d",++count));
Enter fullscreen mode Exit fullscreen mode

in this case the output will be -2147483648 that is clearly an overflow like in previous example.

From Java 8 Math class provides a set of operations (decrementExact, addExact,multiplyExact, etc. ) for "checked" arithmetic operations against numeric overflow/underflow.

To trigger an overflow exception we need to use Math.incrementExact that returns the argument incremented by one, throwing an exception if the result overflows an int.

Integer count=Integer.MAX_VALUE; // 2147483647
Math.incrementExact(count);
Enter fullscreen mode Exit fullscreen mode

here we go, the exception is served:

Exception in thread "main" java.lang.ArithmeticException: integer overflow at java.base/java.lang.Math.incrementExact(Math.java:964)
at Main.main(Main.java:12)

JavaScript

In JavaScript too we don't have an overflow exception if we increment a maximum value of a number and, at moment of writing, there is no way to detect a numeric overflow exception unless you write a custom function to reach this goal.

Let's prove that.

let counter=Number.MAX_VALUE;
console.log(++counter);
Enter fullscreen mode Exit fullscreen mode

In the previous snippet we are incrementing by one the maximum value of Number represented by the constant Number.MAX_VALUE. The output of this snippet is 1.7976931348623157e+308 the original value of the variable counter (so the increment has non effect).

But how detect an numeric overflow/underflow JavaScript?

In this article from algotech.solutions there are good arithmetic considerations that bring to implement custom functions to detect numeric overflow/underflow.

Python

In Python 3 integers haven't fixed size (this article explain how they are structured) and the only limit is the available memory. For this reason the following code could never stop until the memory is available.

from time import sleep

count=int(0)
step = int(10**10000)
while(True):
    count+=step
    sleep(0.2)
Enter fullscreen mode Exit fullscreen mode

If we want have more control about the dimension of the integers we can use NumPy

import sys
import numpy as np

count=np.int64(sys.maxsize)
count+=1
Enter fullscreen mode Exit fullscreen mode

Here we go the exception is served:
RuntimeWarning: overflow encountered in long_scalars
count+=1
-9223372036854775808

Conclusions

Detecting a numeric overflow/underflow is expensive and for this reason many programming languages have as default behavior to ignore it and leave to the programmer to decide if check or uncheck an arithmetic operation.

What's really matters is the knowledge of the problem and how the implementation of the programming language approaches to this kind of situations. Ignoring or overlooking the problem could lead to an unexpected results and security flaws (in some scenarios).

This article has been written because many years ago I wrote an algorithm for a challenge on Hackerrank and a silent overflow made fail it (long story short I wasted a lot of time to figure out the nature of the problem).

Suggestions and corrections are welcome.

See you

AM

. . . . . . . . . . . . . . .
Terabox Video Player