Integer overflow
Some languages support one or more integer types of the underlying processor. This integer types have fixed size. Usually 8-bit, 16-bit, 32-bit or 64-bit. The integers supported by such a type can be signed or unsigned. Arithmetic for machine level integers can often be done by single CPU instructions. This allows high performance and is the main reason to support machine level integers.
An integer overflow happens when the result of a computation does not fit into the fixed size integer. The result can be too small or too big to be representable in the fixed size integer.
When a language has fixed size integer types, the task is to write a program that does arithmetic compitations for the fixed size integers of the language. This computations must be done such that the result would overflow. The program should demonstate what the following expressions do. For 32-bit signed integers:
-(-2147483647-1) 2000000000 + 2000000000 -2147483647 - 2147483647 46341 * 46341 (-2147483647-1) / -1
For 64-bit signed integers:
-(-9223372036854775807-1) 5000000000000000000+5000000000000000000 -9223372036854775807 - 9223372036854775807 3037000500 * 3037000500 (-9223372036854775807-1) / -1
For 32-bit unsigned integers:
-4294967295 3000000000 + 3000000000 2147483647 - 4294967295 65537 * 65537
For 64-bit unsigned integers:
-18446744073709551615 10000000000000000000 + 10000000000000000000 9223372036854775807 - 18446744073709551615 4294967296 * 4294967296
When the integer overflow does trigger an exception show how the exception is catched. When the integer overflow produces some value print it. This should be done for signed and unsigned integers of various sizes supported by the language. When a language has no fixed size integer type or when no integer overflow can occur for other reasons this should be noted. It is okay to mention, when a language supports unlimited precision integers, but this task is NOT the place to demonstrate the capabilities of unlimited precision integers.
C
C supports integer types of various sizes with and without signedness. Unsigned integer aritmethic is defined to be modulus a power of two. An overflow for signed integer arithmetic is undefined behavior. <lang c>#include <stdio.h>
int main (int argc, char *argv[]) {
printf("Signed 32-bit:\n"); printf("%d\n", -(-2147483647-1)); printf("%d\n", 2000000000 + 2000000000); printf("%d\n", -2147483647 - 2147483647); printf("%d\n", 46341 * 46341); printf("%d\n", (-2147483647-1) / -1); printf("Signed 64-bit:\n"); printf("%ld\n", -(-9223372036854775807-1)); printf("%ld\n", 5000000000000000000+5000000000000000000); printf("%ld\n", -9223372036854775807 - 9223372036854775807); printf("%ld\n", 3037000500 * 3037000500); printf("%ld\n", (-9223372036854775807-1) / -1); printf("Unsigned 32-bit:\n"); printf("%u\n", -4294967295U); printf("%u\n", 3000000000U + 3000000000U); printf("%u\n", 2147483647U - 4294967295U); printf("%u\n", 65537U * 65537U); printf("Unsigned 64-bit:\n"); printf("%lu\n", -18446744073709551615LU); printf("%lu\n", 10000000000000000000LU + 10000000000000000000LU); printf("%lu\n", 9223372036854775807LU - 18446744073709551615LU); printf("%lu\n", 4294967296LU * 4294967296LU); return 0;
}</lang>
- Output:
Signed 32-bit: -2147483648 -294967296 2 -2147479015 -2147483648 Signed 64-bit: -9223372036854775808 -8446744073709551616 2 -9223372036709301616 -9223372036854775808 Unsigned 32-bit: 1 1705032704 2147483648 131073 Unsigned 64-bit: 1 1553255926290448384 9223372036854775808 0
Java
The type int is a signed 32-bit integer and the type long is a 64-bit integer. <lang java>public class integerOverflow {
public static void main(String[] args) { System.out.println("Signed 32-bit:"); System.out.println(-(-2147483647-1)); System.out.println(2000000000 + 2000000000); System.out.println(-2147483647 - 2147483647); System.out.println(46341 * 46341); System.out.println((-2147483647-1) / -1); System.out.println("Signed 64-bit:"); System.out.println(-(-9223372036854775807L-1)); System.out.println(5000000000000000000L+5000000000000000000L); System.out.println(-9223372036854775807L - 9223372036854775807L); System.out.println(3037000500L * 3037000500L); System.out.println((-9223372036854775807L-1) / -1); }
}</lang>
- Output:
Signed 32-bit: -2147483648 -294967296 2 -2147479015 -2147483648 Signed 64-bit: -9223372036854775808 -8446744073709551616 2 -9223372036709301616 -9223372036854775808
Seed7
Seed7 supports unlimited precision integers with the type bigInteger. The type integer is a 64-bit signed integer type. All computations with the type integer are checked for overflow. The program below surrounds every writeln statement with a block. Normally much larger blocks would be used. <lang seed7>$ include "seed7_05.s7i";
const proc: main is func
begin block writeln(-(-9223372036854775807-1)); exception catch OVERFLOW_ERROR: writeln("OVERFLOW_ERROR"); end block; block writeln(5000000000000000000+5000000000000000000); exception catch OVERFLOW_ERROR: writeln("OVERFLOW_ERROR"); end block; block writeln(-9223372036854775807 - 9223372036854775807); exception catch OVERFLOW_ERROR: writeln("OVERFLOW_ERROR"); end block; block writeln(3037000500 * 3037000500); exception catch OVERFLOW_ERROR: writeln("OVERFLOW_ERROR"); end block; block writeln((-9223372036854775807-1) div -1); exception catch OVERFLOW_ERROR: writeln("OVERFLOW_ERROR"); end block; end func;</lang>
- Output:
OVERFLOW_ERROR OVERFLOW_ERROR OVERFLOW_ERROR OVERFLOW_ERROR OVERFLOW_ERROR