Integer overflow: Difference between revisions

Replaced the existing program which doesn't actually checked overflow for int32 and uint32 by another one.
(Added description of Nim overflow detection.)
(Replaced the existing program which doesn't actually checked overflow for int32 and uint32 by another one.)
Line 1,512:
 
=={{header|Nim}}==
 
===General behavior regarding overflow===
 
In Nim, overflow during operations on signed integers is detected and raises an exception. Starting from version 1.4, overflows are defects. For now, by default, defects can be caught but in future versions this may and probably would change. Using compile option <code>--panics:on</code> makes defects impossible to catch.
Line 1,538 ⟶ 1,540:
 
===Program to check behavior when overflow is not detected===
This program presents the behavior when overflow checks are suppressed. Remember that for signed integers, this is not the normal behavior and that the result is always wrong when an overflow occurs.
 
<lang Nim>echo "For 32 bits signed integers with overflow check suppressed:"
Note also that some of the UInt64 tests not tested in the code because they raise compile-time errors (alerting the programmer to range errors). The exception text has been included for completeness.
{.push overflowChecks: off.}
 
var a: int32
<lang Nim>import macros, strutils
a = -(-2147483647i32 - 1'i32)
echo " -(-2147483647-1) gives ", a # -2147483648.
a = 2000000000i32 + 2000000000i32
echo " 2000000000 + 2000000000 gives ", a # -294967296.
a = -2147483647i32 - 2147483647i32
echo " -2147483647 - 2147483647 gives ", a # 2.
a = 46341i32 * 46341i32
echo " 46341 * 46341 gives ", a # -2147479015.
a = (-2147483647i32 - 1i32) div -1i32
echo " (-2147483647-1) / -1 gives ", a # -2147483648.
{.pop.}
echo ""
 
echo "For 64 bits signed integers with overflow check suppressed:"
{.push overflowChecks: off.}
var b: int64
b = -(-9223372036854775807i64 - 1i64)
echo " -(-9223372036854775807-1) gives ", b # -9223372036854775808.
b = 5000000000000000000i64 + 5000000000000000000i64
echo " 5000000000000000000 + 5000000000000000000 gives ", b # -8446744073709551616.
b = -9223372036854775807i64 - 9223372036854775807i64
echo " -9223372036854775807 - 9223372036854775807 gives ", b # 2.
b = 3037000500i64 * 3037000500i64
echo " 3037000500 * 3037000500 gives ", b # -9223372036709301616.
b = (-9223372036854775807i64 - 1i64) div -1i64
echo " (-9223372036854775807-1) / -1 gives ", b # -9223372036854775808.
{.pop.}
echo ""
 
echo "For 32 bits unsigned integers:"
macro toIntVal(s: static[string]): untyped =
var c: uint32
result = parseExpr(s)
echo " -4294967295 doesn’t compile."
c = 3000000000u32 + 3000000000u32
echo " 3000000000 + 3000000000 gives ", c # 1705032704.
c = 2147483647u32 - 4294967295u32
echo " 2147483647 - 4294967295 gives ", c # 2147483648.
c = 65537u32 * 65537u32
echo " 65537 * 65537 gives ", c # 131073.
echo ""
 
echo "For 64 bits unsigned integers:"
proc `/`(x,y:int64): float = return (x.float / y.float)
var d: uint64
echo " -18446744073709551615 doesn’t compile."
d = 10000000000000000000u64 + 10000000000000000000u64
echo " 10000000000000000000 + 10000000000000000000 gives ", d # 1553255926290448384.
d = 9223372036854775807u64 - 18446744073709551615u64
echo " 9223372036854775807 - 18446744073709551615 gives ", d # 9223372036854775808.
d = 4294967296u64 * 4294967296u64
echo " 4294967296 * 4294967296 gives ", d # 0.</lang>
 
{{out}}
const
<pre>For 32 bits signed integers with overflow check suppressed:
strInt32 = ["-(-2147483647-1)",
-(-2147483647-1) gives -2147483648
"2_000_000_000 + 2_000_000_000",
2000000000 + 2000000000 gives -294967296
"-2147483647 - 2147483647",
-2147483647 - 2147483647 gives 2
"46341 * 46341",
46341 * 46341 gives -2147479015
"(-2147483647-1) / -1"]
shouldBInt32(-2147483647-1) =/ ["-1 gives -2147483648",
"4000000000",
"-4294967294",
"2147488281",
"2147483648"]
strInt64 = ["-(-9_223372_036854_775807-1) ",
"5_000000_000000_000000+5_000000_000000_000000",
"-9_223372_036854_775807 - 9_223372_036854_775807",
"3037_000500 * 3037_000500",
"(-9_223372_036854_775807-1) / -1"]
shouldBInt64 = ["9223372036854775808",
"10000000000000000000",
"-18446744073709551614",
"9223372037000250000",
"9223372036854775808"]
strUInt32 = ["-4294967295",
"3000_000000 +% 3000_000000",
"2147483647 -% 4294967295",
"65537 *% 65537"]
shouldBUInt32 = ["-4294967295",
"6000000000",
"-2147483648",
"4295098369"]
strUInt64 = ["-18446744073709551615",
"10_000000_000000_000000 +% 10_000000_000000_000000",
"9_223372_036854_775807 -% 18_446744_073709_551615",
"4294967296 * 4294967296",
"4294967296 *% 4294967296",] # testing * and *%
shouldBUInt64 = ["-18446744073709551615",
"20000000000000000000",
"-9223372036854775808",
"18446744073709551616",
"18446744073709551616"]
#
# use compile time macro to convert string expr to numeric value
#
var
resInt32: seq[string] = @[$toIntVal(strInt32[0]),
$toIntVal(strInt32[1]),
$toIntVal(strInt32[2]),
$toIntVal(strInt32[3]),
$toIntVal(strInt32[4])]
 
For 64 bits signed integers with overflow check suppressed:
resInt64: seq[string] = @[$toIntVal(strInt64[0]),
-(-9223372036854775807-1) gives -9223372036854775808
$toIntVal(strInt64[1]),
5000000000000000000 + 5000000000000000000 gives -8446744073709551616
$toIntVal(strInt64[2]),
-9223372036854775807 - 9223372036854775807 gives 2
$toIntVal(strInt64[3]),
3037000500 * 3037000500 gives -9223372036709301616
$toIntVal(strInt64[4])]
(-9223372036854775807-1) / -1 gives -9223372036854775808
 
For 32 bits unsigned integers:
resUInt32: seq[string] = @[$toIntVal(strUInt32[0]),
-4294967295 doesn’t compile.
$toIntVal(strUInt32[1]),
3000000000 + 3000000000 gives 1705032704
$toIntVal(strUInt32[2]),
2147483647 - 4294967295 gives 2147483648
$toIntVal(strUInt32[3])]
65537 * 65537 gives 131073
 
For 64 bits unsigned integers:
resUInt64: seq[string] = @["18446744073709551615 out of valid range",
-18446744073709551615 doesn’t compile.
"10_000000_000000_000000 out of valid range",
10000000000000000000 + 10000000000000000000 gives 1553255926290448384
"18_446744_073709_551615 out of valid range",
9223372036854775807 - 18446744073709551615 gives 9223372036854775808
$toIntVal(strUInt64[3]),
4294967296 * 4294967296 gives 0</pre>
$toIntVal(strUInt64[4])]
 
proc main() =
# output format:
#
# stringExpr -> calculatedValueAsAString (expectedValueAsAString)
echo "-- INT32 --"
for i in 0..<resInt32.len:
echo align(strInt32[i], 35), " -> ", align($resInt32[i], 15), " (", $shouldBInt32[i],")"
 
echo "-- INT64 --"
for i in 0..<resInt64.len:
echo align(strInt64[i], 55), " -> ", align($resInt64[i], 25), " (", $shouldBInt64[i],")"
 
echo "-- UINT32 --"
for i in 0..<resUInt32.len:
echo align(strUInt32[i], 35), " -> ", align($resUInt32[i], 20), " (", $shouldBUInt32[i],")"
 
echo "-- UINT64 --"
for i in 0..<resUInt64.len:
echo align(strUInt64[i], 55), " -> ", align($resUInt64[i], 42), " (", $shouldBUInt64[i],")"
 
main()
{.pop.}</lang>
 
{{out}}
<pre>-- INT32 --
-(-2147483647-1) -> 2147483648 (2147483648)
2_000_000_000 + 2_000_000_000 -> 4000000000 (4000000000)
-2147483647 - 2147483647 -> -4294967294 (-4294967294)
46341 * 46341 -> 2147488281 (2147488281)
(-2147483647-1) / -1 -> 2147483648.0 (2147483648)
-- INT64 --
-(-9_223372_036854_775807-1) -> -9223372036854775808 (9223372036854775808)
5_000000_000000_000000+5_000000_000000_000000 -> 9223372036854775807 (10000000000000000000)
-9_223372_036854_775807 - 9_223372_036854_775807 -> -9223372036854775808 (-18446744073709551614)
3037_000500 * 3037_000500 -> 9223372036854775807 (9223372037000250000)
(-9_223372_036854_775807-1) / -1 -> 9.223372036854776e+018 (9223372036854775808)
-- UINT32 --
-4294967295 -> -4294967295 (-4294967295)
3000_000000 +% 3000_000000 -> 6000000000 (6000000000)
2147483647 -% 4294967295 -> -2147483648 (-2147483648)
65537 *% 65537 -> 4295098369 (4295098369)
-- UINT64 --
-18446744073709551615 -> 18446744073709551615 out of valid range (-18446744073709551615)
10_000000_000000_000000 +% 10_000000_000000_000000 -> 10_000000_000000_000000 out of valid range (20000000000000000000)
9_223372_036854_775807 -% 18_446744_073709_551615 -> 18_446744_073709_551615 out of valid range (-9223372036854775808)
4294967296 * 4294967296 -> 9223372036854775807 (18446744073709551616)
4294967296 *% 4294967296 -> 0 (18446744073709551616)
</pre>
 
=={{header|Oforth}}==
Anonymous user