1. Arbitrary Precision Integers
In most languages, integers have fixed sizes (32-bit, 64-bit) and overflow silently or throw errors. Python is different: integers have unlimited precision.
>>> 2 ** 100 1267650600228229401496703205376 >>> 2 ** 1000 # Returns a 302-digit number without breaking a sweat
- No overflow bugs — You'll never wrap around to a negative number unexpectedly
- No int vs long distinction — Python 3 unified these; there's just
int - Trade-off: Performance — Very large integers are slower because Python uses software-based arbitrary precision arithmetic instead of CPU-native operations
import math # This is fine factorial_100 = math.factorial(100) # 158-digit number, instant # This gets slow factorial_100000 = math.factorial(100000) # Takes noticeable time
For cryptographic or scientific work with huge numbers, libraries like gmpy2 provide faster arbitrary-precision math.
2. Float Representation and Pitfalls
Python floats are IEEE 754 double-precision (64-bit), identical to double in C or Java. This isn't unique to Python, but the consequences surprise developers.
The Classic Trap
>>> 0.1 + 0.2 0.30000000000000004 >>> 0.1 + 0.2 == 0.3 False
0.1 and 0.2 can't be represented exactly in binary floating point — they're approximations. This affects every language using IEEE 754, not just Python.
How to Handle This
Option 1: Tolerance-based comparison
>>> abs((0.1 + 0.2) - 0.3) < 1e-9 True # Or use math.isclose (Python 3.5+) >>> import math >>> math.isclose(0.1 + 0.2, 0.3) True
Option 2: Use Decimal for exact decimal arithmetic
from decimal import Decimal # Always pass strings to Decimal, not floats >>> Decimal('0.1') + Decimal('0.2') == Decimal('0.3') True # If you pass a float, you inherit its imprecision >>> Decimal(0.1) Decimal('0.1000000000000000055511151231257827021181583404541015625')
Option 3: Use Fraction for exact rational arithmetic
from fractions import Fraction >>> Fraction(1, 10) + Fraction(2, 10) == Fraction(3, 10) True >>> Fraction('0.1') + Fraction('0.2') Fraction(3, 10)
When to Use What
| Use Case | Type |
|---|---|
| General math, science, graphics | float |
| Money, financial calculations | Decimal |
| Exact ratios, symbolic math | Fraction |
| Large integer math, cryptography | int |
3. Division Behavior
Python 3 changed division semantics, which trips up developers coming from Python 2, C, or Java.
True Division vs Floor Division
>>> 5 / 2 # True division: always returns a float 2.5 >>> 5 // 2 # Floor division: returns an integer (if both operands are int) 2 >>> 5.0 // 2 # Floor division with float operand: returns a float 2.0
The Floor-Toward-Negative-Infinity Gotcha
This is where Python differs from C, Java, and many other languages:
>>> -5 // 2 -3 # -5 / 2 = -2.5 # Floor DOWN to -3
// -5 / 2 in C or Java: -2 // -5 / 2 = -2.5 // Truncate TOWARD ZERO to -2
Floor division and modulo (%) are mathematically consistent in Python. The invariant (a // b) * b + (a % b) == a always holds. This makes modulo behave predictably with negative numbers — useful for things like circular array indexing.
Modulo With Negative Numbers
>>> -5 % 2 1 # Python: result has same sign as divisor # In C: -5 % 2 might give -1 (result has same sign as dividend) # Verify the invariant: >>> a, b = -5, 2 >>> (a // b) * b + (a % b) -5 # Always equals a
4. Booleans Are Integers
This is genuinely surprising: bool is a subclass of int.
>>> isinstance(True, int) True >>> True == 1 True >>> False == 0 True
This Enables Useful Patterns
# Counting with sum: >>> data = [1, -5, 3, -2, 8] >>> sum(x > 0 for x in data) # Count positive numbers 3 # Conditional arithmetic: >>> discount_eligible = True >>> price = 100 - (20 * discount_eligible) # 80 if eligible, 100 if not 80 # Indexing with booleans: >>> options = ["no", "yes"] >>> options[True] 'yes' >>> options[False] 'no'
The Gotcha
>>> True + True + True 3 >>> sum([True, True, False]) 2 # True == 1 and False == 0, so they're duplicates in sets! >>> {1, True, 0, False} {0, 1}
Because True == 1 and False == 0, they hash to the same values. In sets and dict keys, True and 1 are considered the same key, as are False and 0.
5. Numeric Literals and Readability
Underscores (Python 3.6+)
You can use underscores anywhere in numeric literals for readability. Python ignores them entirely — they're purely visual:
million = 1_000_000 credit_card = 1234_5678_9012_3456 binary = 0b_1111_0000_1010_0101 hex_color = 0xFF_FF_FF
Different Bases
decimal = 255 binary = 0b11111111 # prefix: 0b octal = 0o377 # prefix: 0o hexadecimal = 0xFF # prefix: 0x # All four are equal >>> decimal == binary == octal == hexadecimal True
Complex Numbers (Built-in!)
Python has native complex number support:
>>> z = 3 + 4j >>> z.real 3.0 >>> z.imag 4.0 >>> abs(z) # Magnitude 5.0 >>> z.conjugate() (3-4j)
6. Common Mistakes and Edge Cases
Mistake 1: Division by Zero
>>> 1 / 0 # ZeroDivisionError >>> 1.0 / 0.0 # ZeroDivisionError — Python doesn't return infinity like some languages # But float infinity exists: >>> float('inf') inf >>> float('inf') > 10**1000 True
Mistake 2: Assuming Integer Results
def split_evenly(total, parts): return total / parts >>> split_evenly(10, 2) 5.0 # float, not int
def split_evenly(total, parts): result = total / parts if result.is_integer(): return int(result) return result
Mistake 3: Float Comparison in Loops
x = 0.0 while x != 1.0: x += 0.1 print(x) # After 10 iterations, x is # 0.9999999999999999, not 1.0
x = 0.0 while x < 1.0: x += 0.1 print(x)
Mistake 4: Decimal from Float
>>> Decimal(0.1) Decimal('0.100000000000000 0055511151231257827021 181583404541015625')
>>> Decimal('0.1') Decimal('0.1')
7. Special Float Values
Python supports IEEE 754 special values:
>>> float('inf') # Positive infinity inf >>> float('-inf') # Negative infinity -inf >>> float('nan') # Not a Number nan
NaN comparisons are always False, even with itself. This is the only value in Python where x == x is False.
>>> x = float('nan') >>> x == x False # Use math.isnan() to check >>> import math >>> math.isnan(x) True
Quick Reference: Python vs C/Java
| Feature | Python | C / Java |
|---|---|---|
| Integer overflow | Never (arbitrary precision) | Wraps around or error |
5 / 2 | 2.5 (float) | 2 (integer) |
-5 // 2 | -3 (floor toward -∞) | -2 (truncate toward 0) |
-5 % 2 | 1 (sign of divisor) | -1 (sign of dividend) |
bool type | Subclass of int | Separate type |
| Complex numbers | Built-in (3+4j) | Requires library |
Summary: Key Takeaways
| Concept | Key Takeaway |
|---|---|
| Arbitrary precision | Python integers never overflow, but very large numbers are slower |
| Float comparison | Never use == with floats — use math.isclose() or tolerance |
| Decimal & Fraction | Use Decimal('0.1') (strings!) for money, Fraction for exact ratios |
| Division | / always returns float, // floors toward negative infinity |
| Booleans | bool is a subclass of int — True == 1, False == 0 |
| Readability | Use underscores in literals: 1_000_000, 0xFF_FF |
| NaN | NaN != NaN — always use math.isnan() to check |