Integer Overflow and Floating-Point Limitations
After completing this topic, you will be able to:
- Understand why integer overflows occur.
- Explain the precision limitations of floating-point numbers.
- Know the precautions to take when comparing numerical values.
Computers Make Mistakes with Numbers
print(0.1 + 0.2) # 0.30000000000000004print(0.1 + 0.2 == 0.3) # False!This is not a bug in Python. It's the same in C, Java, JavaScript, Rustβall languages. It's because of how computers store decimal numbers.
Integer Overflow
Bits and Range
Integers in computers are represented with a fixed number of bits.
8-bit unsigned integer: 0 ~ 255
8-bit signed integer: -128 ~ 127
32-bit signed integer: -2,147,483,648 ~ 2,147,483,647
64-bit signed integer: -9.2 Γ 10^18 ~ 9.2 Γ 10^18If you exceed the range, an overflow occurs.
The Reality of Overflow
In an 8-bit unsigned integer, what is 255 + 1?
11111111 (255)
+ 00000001 (1)
----------
100000000 (256 β but the 9th bit is truncated!)
= 00000000 (0)The result wraps around to 0! This is an overflow. It's like an odometer on a car rolling over from 999,999 to 000,000.
Real-World Examples
// C language β 32-bit integer overflow
int balance = 2147483647; // Maximum value
balance = balance + 1; // -2147483648! (Positive becomes negative)- Ariane 5 rocket explosion (1996): Converting a 64-bit value to a 16-bit value β overflow β rocket self-destructed.
- Gangnam Style YouTube views (2014): Exceeded the 32-bit integer limit (2 billion) β Google switched to 64-bit.
Python Doesn't Have Overflow
# Python has no limit on integer sizebig = 2 ** 100print(big) # 1267650600228229401496703205376
bigger = 2 ** 1000print(len(str(bigger))) # 302 digits!Python automatically expands memory as needed. However, in most languages like C, Java, and JavaScript, integer sizes are fixed, so you need to be careful about overflows.
NumPy also has overflowsβNumPy arrays use C-style fixed-size integers:
import numpy as np
a = np.int32(2147483647)print(a + 1) # -2147483648 (Overflow!)
b = np.int64(2147483647)print(b + 1) # 2147483648 (Safe in 64-bit)Floating-Point β IEEE 754
Converting 0.1 to Binary
Just as 1/3 = 0.333333... is an infinite decimal in base-10, 0.1 = 0.0001100110011... is an infinite binary number.
0.1 (base-10) = 0.00011001100110011001100110011... (base-2, infinitely repeating)Computers store this infinite number in a finite number of bits (64 bits), so it has to be truncated somewhere. This truncation is the cause of the error.
IEEE 754 β 64-bit Floating-Point
[1-bit sign][11-bit exponent][52-bit mantissa]
0 01111111011 1001100110011001100110011001100110011001100110011010
Sign: 0 (positive)
Exponent: Determines the actual exponent
Mantissa: Significant digits (52 bits β 15-17 digits of precision)# Accurate up to 15-17 digitsprint(f"{0.1:.20f}") # 0.10000000000000000555print(f"{0.2:.20f}") # 0.20000000000000001110print(f"{0.3:.20f}") # 0.29999999999999998890Neither 0.1 nor 0.2 is accurate, so the sum is also inaccurate.
Practical Problems and Solutions
1. Comparison β Never compare with ==
# Badif 0.1 + 0.2 == 0.3: print("Equal") # Doesn't execute!
# Good β Use tolerance (epsilon)epsilon = 1e-9if abs((0.1 + 0.2) - 0.3) < epsilon: print("Equal") # Executes
# Better β Use math.iscloseimport mathif math.isclose(0.1 + 0.2, 0.3): print("Equal") # Executes2. Cumulative Error β Grows in iterative calculations
total = 0.0for _ in range(1000): total += 0.1print(total) # 99.99999999999857 (Not 100!)print(f"Error: {abs(total - 100):.15f}") # 0.0000000000014323. Financial Calculations β Use Decimal
from decimal import Decimal
# float β error occursprice = 0.1 + 0.2print(price) # 0.30000000000000004
# Decimal β accurateprice = Decimal('0.1') + Decimal('0.2')print(price) # 0.3 (accurate!)
# Note: Must be initialized as a stringDecimal(0.1) # Decimal('0.1000000000000000055511151231257827021181583404541015625')Decimal('0.1') # Decimal('0.1') β accurateFor calculations where accuracy is important (amounts, taxes, interest rates), use Decimal instead of float.
JavaScript Numbers β Integers are also Floating-Point
JavaScript doesn't have an integer type. All numbers are 64-bit floating-point (IEEE 754).
// JavaScript β Loss of precision in large integers
console.log(9007199254740992 === 9007199254740993); // true!
// The numbers are considered equal because they exceed the 52-bit mantissa
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 (2^53 - 1)This is why BigInt was introduced in JavaScript:
const big = 9007199254740993n; // BigInt literal (n suffix)
console.log(big === 9007199254740993n); // true β accurateThe reason why Twitter (now X) passes tweet IDs as strings is also this: parsing them as numbers in JSON would result in a loss of precision, so the API also provides the ID as a string "id_str".
Special Values
# Infinityprint(float('inf')) # infprint(float('inf') + 1) # infprint(float('inf') * -1) # -inf
# NaN (Not a Number)print(float('nan')) # nanprint(float('nan') == float('nan')) # False! (NaN is not equal to itself)
import mathprint(math.isnan(float('nan'))) # True (correct way to check)print(math.isinf(float('inf'))) # TrueNaN is the only value that is not equal to itself. Always use math.isnan() to check for NaN.
Key Takeaways
| Concept | Summary |
|---|---|
| Integer Overflow | Values wrap around when exceeding the fixed number of bits. Python is an exception (automatic expansion). |
| IEEE 754 | 64-bit floating-point standard. 52-bit mantissa β 15-17 digits of precision. |
| 0.1 + 0.2 β 0.3 | 0.1 is an infinite decimal in base-2 β truncation during storage β error. |
| Comparison | Use math.isclose() instead of ==. |
| Financial Calculations | Use Decimal instead of float. |
| NaN | Not equal to itself. Check with math.isnan(). |
The misconception is that "computers calculate accurately." Computers have a fundamental limitation in precision because they represent infinite numbers with finite bits. Understanding this limitation clarifies why Decimal is used in financial systems, why coordinates "jitter" in games, and why error analysis is necessary in scientific calculations.
Practical rules: Integers: safe in Python, check range in other languages. Floating-point: never use ==, use Decimal for finance. Check for NaN with math.isnan().