Integer overflow: Difference between revisions

New post showing additional methods introduced in Java 8, in addition to an existing post which was retained.
m (syntax highlighting fixup automation)
(New post showing additional methods introduced in Java 8, in addition to an existing post which was retained.)
 
(7 intermediate revisions by 4 users not shown)
Line 858:
 
-2147479015 true</pre>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
As demonstrated by the program below, the Delphi catches these overflow conditions before they can be compiled.
 
 
<syntaxhighlight lang="Delphi">
 
 
var IS32: integer; {Signed 32-bit integer}
var IS64: Int64; {Signed 64-bit integer}
var IU32: cardinal; {Unsigned 32-bit integer}
 
{============ Signed 32 bit tests ===================================}
 
procedure TestSigned32_1;
begin
IS32:=-(-2147483647-1);
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
procedure TestSigned32_2;
begin
IS32:=2000000000 + 2000000000;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
 
procedure TestSigned32_3;
begin
IS32:=-2147483647 - 2147483647;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
procedure TestSigned32_4;
begin
IS32:=46341 * 46341;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
 
procedure TestSigned32_5;
begin
IS32:=(-2147483647-1) div -1;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
{============ Signed 64 bit tests ===================================}
 
procedure TestSigned64_1;
begin
IS64:=-(-9223372036854775807-1);
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
procedure TestSigned64_2;
begin
IS64:=5000000000000000000+5000000000000000000;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
procedure TestSigned64_3;
begin
IS64:=-9223372036854775807 - 9223372036854775807;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
procedure TestSigned64_4;
begin
IS64:=3037000500 * 3037000500;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
procedure TestSigned64_5;
begin
IS64:=(-9223372036854775807-1) div -1;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
{============ UnSigned 32 bit tests ===================================}
 
procedure TestUnSigned32_1;
begin
IU32:=-4294967295;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
procedure TestUnSigned32_2;
begin
IU32:=3000000000 + 3000000000;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
procedure TestUnSigned32_3;
begin
IU32:=2147483647 - 4294967295;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
procedure TestUnSigned32_4;
begin
IU32:=65537 * 65537;
end;
 
// Compiler: "Overflow in conversion or arithmetic operation"
 
 
//Delphi-6 does not have 64-bit unsigned integers.
//Later version have 64-bit unsigned integers.
 
</syntaxhighlight>
{{out}}
<pre>
 
</pre>
 
=={{header|Factor}}==
Line 1,424 ⟶ 1,563:
The type int is a signed 32-bit integer and the type long is a 64-bit integer.
A Java program does <b>not</b> recognize an integer overflow and the program <b>continues with wrong results</b>.
<syntaxhighlight lang="java">public class integerOverflowIntegerOverflow {
 
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);
}
 
}</syntaxhighlight>
 
Line 1,451 ⟶ 1,588:
-2147479015
-2147483648
Signed 64-bit:
-9223372036854775808
-8446744073709551616
2
-9223372036709301616
-9223372036854775808
</pre>
 
===Using Java 8===
<syntaxhighlight lang="java">
public final class IntegerOverflow {
 
public static void main(String[] args) {
// The following examples show that Java allows integer overflow without warning
// and calculates an incorrect result.
// From version 8, Java introduced methods which throw an ArithmeticException when overflow occurs,
// which prevents the calculation of an incorrect result. It also allows the programmer to replace an "int"
// with a "long" and to replace a "long" with a BigInteger.
// Uncomment the lines below to see the use of the new methods:
// addExact(), subtractExact(), multiplyExact() and negateExact().
System.out.println("Signed 32-bit:");
System.out.println(-(-2_147_483_647 - 1));
// System.out.println(Math.negateExact(-2_147_483_647 - 1));
System.out.println(2_000_000_000 + 2_000_000_000);
// System.out.println(Math.addExact(2_000_000_000, 2_000_000_000));
System.out.println(-2_147_483_647 - 2_147_483_647);
// System.out.println(Math.subtractExact(-2_147_483_647, 2_147_483_647));
System.out.println(46_341 * 46_341);
// System.out.println(Math.multiplyExact(46_341, 46_341));
System.out.println((-2_147_483_647 - 1) / -1);
// System.out.println(Math.negateExact(Math.subtractExact(-2_147_483_647, 1) / 1));
System.out.println();
System.out.println("Signed 64-bit:");
System.out.println(-(-9_223_372_036_854_775_807L - 1));
// System.out.println(Math.negateExact(-9_223_372_036_854_775_807L - 1));
System.out.println(5_000_000_000_000_000_000L + 5_000_000_000_000_000_000L);
// System.out.println(Math.addExact(5_000_000_000_000_000_000L, 5_000_000_000_000_000_000L));
System.out.println(-9_223_372_036_854_775_807L - 9_223_372_036_854_775_807L);
// System.out.println(Math.subtractExact(-9_223_372_036_854_775_807L, 9_223_372_036_854_775_807L));
System.out.println(3_037_000_500L * 3_037_000_500L);
// System.out.println(Math.multiplyExact(3_037_000_500L, 3_037_000_500L));
System.out.println((-9_223_372_036_854_775_807L - 1) / -1);
// System.out.println(Math.negateExact(Math.subtractExact(-9_223_372_036_854_775_807L, 1) / 1));
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
Signed 32-bit:
-2147483648
-294967296
2
-2147479015
-2147483648
 
Signed 64-bit:
-9223372036854775808
Line 1,625 ⟶ 1,829:
A Kotlin program does <b>not</b> recognize a signed integer overflow and the program <b>continues with wrong results</b>.
 
<syntaxhighlight lang="scalakotlin">// version 1.0.5-2
 
/* Kotlin (like Java) does not have unsigned integer types but we can simulate
what would happen if we did have an unsigned 32 bit integer type using this extension function */
fun Long.toUInt(): Long = this and 0xffffffffL
 
// The Kotlin compiler can detect expressions of signed constant integers that will overflow.
// It cannot detect unsigned integer overflow, however.
@Suppress("INTEGER_OVERFLOW")
fun main(args: Array<String>) {
// The following 'signed' computations all produce compiler warnings that they will lead to an overflow
// which have been ignored
println("*** Signed 32 bit integers ***\n")
println(-(-2147483647 - 1))
Line 1,647 ⟶ 1,847:
println(3037000500 * 3037000500)
println((-9223372036854775807 - 1) / -1)
// Simulated unsigned computations, no overflow warnings as we're using the Long type
println("\n*** Unsigned 32 bit integers ***\n")
// println(-4294967295U) // this is a compiler error since unsigned integers have no negation operator
println((-4294967295L).toUInt())
// println((3000000000L.toUInt(0U - 4294967295U) +// 3000000000L.toUInt()).toUInt())this works
println((2147483647L - 4294967295L4294967295).toUInt()). // converting from the signed Int type also produces the overflow; this is intended behavior of toUInt())
println((65537L3000000000U *+ 65537L).toUInt()3000000000U)
println(2147483647U - 4294967295U)
println(65537U * 65537U)
println("\n*** Unsigned 64 bit integers ***\n")
println(0U - 18446744073709551615U) // we cannot convert from a signed type here (since none big enough exists) and have to use subtraction
println(10000000000000000000U + 10000000000000000000U)
println(9223372036854775807U - 18446744073709551615U)
println(4294967296U * 4294967296U)
}</syntaxhighlight>
 
Line 1,679 ⟶ 1,885:
2147483648
131073
 
*** Unsigned 64 bit integers ***
 
1
1553255926290448384
9223372036854775808
0
</pre>
 
Line 2,278 ⟶ 2,491:
-1.00000000E+9 [underflow]
-1.50000000E+9 [underflow]
</pre>
 
=={{header|RPL}}==
RPL can handle unsigned integers, whose size can be set by the user from 2 to 64 bits. This format is provided to help software engineers in low-level programming of a ‘real’ computer, not to speed up calculations: RPL programs go faster when using floating-point numbers.
Let’s work with 64-bit integers, displayed in base 10:
64 STWS DEC
and let’s try to comply with the task:
# -18446744073709551615
is rejected by the command line interpreter (syntax error).
#10000000000000000000 #10000000000000000000 +
#9223372036854775807 #18446744073709551615 -
#4294967296 #4294967296 *
{{out}}
<pre>
3: # 9223372036854775807d
2: # 0d
1: # 0d
</pre>
 
Line 2,722 ⟶ 2,952:
 
However, within this overall framework, Wren also has an unsigned 32-bit integer sub-system when dealing with bitwise operations. All values are converted internally to such integers before the corresponding C bitwise operation is performed (Wren's VM is written in C) and can therefore overflow without warning. Fortunately, we can easily observe these effects by performing the operations required by the task and then (for example) right shifting them by 0 places.
<syntaxhighlight lang="ecmascriptwren">var exprs = [-4294967295, 3000000000 + 3000000000, 2147483647 - 4294967295, 65537 * 65537]
 
for (expr in exprs) System.print(expr >> 0)</syntaxhighlight>
System.print("Unsigned 32-bit:")
for (expr in exprs) System.print(expr >> 0)</syntaxhighlight>
 
{{out}}
Results agree with those for the corresponding C entry above.
871

edits