int: Python vs C¶
Python integers (int) differ fundamentally from integers in low-level languages like C. Understanding this difference prevents many bugs and misconceptions.
Mental Model
C integers are fixed-width registers (32 or 64 bits) that silently overflow. Python integers are arbitrary-precision: they grow as large as memory allows, with no overflow. The trade-off is that Python integers are heap-allocated objects with higher memory overhead and slower arithmetic than raw machine integers.
Fixed-size vs¶
1. C integers¶
- Fixed size (e.g. 32-bit or 64-bit)
- Overflow wraps around or is undefined
c
int x = INT_MAX;
x = x + 1; // overflow
2. Python integers¶
- Arbitrary precision
- No overflow (memory grows as needed)
python
x = 10**100
print(x)
Memory¶
- C
int: stored directly in a fixed number of bits - Python
int: object containing - sign
- length
- array of machine words
This makes Python int:
- slower than C
int - but mathematically safe
Semantics¶
Python integers obey mathematical integer semantics:
- exact arithmetic
- no overflow surprises
This is crucial for:
- financial calculations
- cryptography
- symbolic computation
Performance¶
Because Python int is an object:
- arithmetic is slower than in C
- large integers cost more memory
For heavy numerical work, libraries like NumPy use fixed-size types internally.
Key takeaways¶
- Python
inthas arbitrary precision. - No overflow, but higher memory and CPU cost.
- Safer semantics than C for finance and math.
Exercises¶
Exercise 1.
Compute 2 ** 1000 in Python and print the number of digits. Explain why this works in Python but would overflow in C.
Solution to Exercise 1
python
result = 2 ** 1000
num_digits = len(str(result))
print(f"2^1000 has {num_digits} digits") # 302 digits
Python integers have arbitrary precision -- they grow as needed. In C, a 64-bit long can hold at most about 19 digits before overflowing.
Exercise 2.
Use sys.getsizeof() to compare the memory usage of the integers 0, 1, 2**30, and 2**1000. Explain the pattern.
Solution to Exercise 2
```python import sys
for val in [0, 1, 230, 21000]: size = sys.getsizeof(val) print(f"getsizeof({str(val)[:20]:>20s}...) = {size} bytes") ```
Small integers use a fixed base size. As the value grows, Python allocates additional machine words to store the extra digits, so 2**1000 uses significantly more memory than 1.
Exercise 3.
Write a function factorial_digits(n) that computes n! and returns the number of decimal digits in the result. Test with n = 100. Explain why Python can handle this while C int or long cannot.
Solution to Exercise 3
```python import math
def factorial_digits(n): result = math.factorial(n) return len(str(result))
print(f"100! has {factorial_digits(100)} digits") # 158 digits ```
100! is a 158-digit number. Python handles this naturally because int has arbitrary precision. A C unsigned long long (64 bits) overflows at about 20!.