Python Numbers and Operators


  • Description: int with arbitrary precision, float, complex, / vs //, **, divmod, bit ops, comparison chaining, and the math/decimal/fractions modules
  • My Notion Note ID: K2A-D1-4
  • Created: 2022-04-20
  • Updated: 2026-05-11
  • License: Reuse is very welcome. Please credit Yu Zhang and link back to the original on yuzhang.io

Table of Contents


1. Numeric Types

1.1 int Has Arbitrary Precision

  • Unbounded, grows to whatever bits are needed
  • No int32/int64/long long, no C++-style overflow
  • Cost: slower than C++ ints (every + allocates); use NumPy arrays for tight numeric loops
2 ** 100           # 1267650600228229401496703205376
10 ** 1000         # works fine, thousands of digits
import sys; sys.getsizeof(10 ** 1000)   # ~500 bytes

1.2 float Is IEEE 754 Double

  • Same precision as C++ double, same gotchas
0.1 + 0.2          # 0.30000000000000004
0.1 + 0.2 == 0.3   # False
import math
math.isclose(0.1 + 0.2, 0.3)   # True, use for equality

1.3 complex

  • Built-in; j is the imaginary unit
z = 2 + 3j
z.real            # 2.0
z.imag            # 3.0
abs(z)            # 3.605551275463989
(1 + 2j) * (3 + 4j)   # (-5+10j)

1.4 bool Is a Subclass of int

  • True == 1, False == 0, True + 1 == 2
True + True              # 2
isinstance(True, int)    # True

2. Arithmetic Operators

2.1 / vs //

7 / 2     # 3.5 , true division, always float
7 // 2    # 3   , floor division
-7 // 2   # -4  , floors toward -∞ (NOT C truncation!)
7 % 2     # 1
-7 % 2    # 1   , sign follows divisor (Python), not dividend (C)
  • Major C++ pitfall: in C++ -7 / 2 == -3, -7 % 2 == -1
  • Python takes the mathematically cleaner option

2.2 ** and pow

2 ** 10              # 1024
2 ** 0.5             # 1.4142135623730951
pow(3, 5, 7)         # 5  , (3 ** 5) % 7, efficient
  • pow(a, b, m) is modular exponentiation, useful for crypto

2.3 divmod

  • Returns (quotient, remainder) in one call
divmod(17, 5)        # (3, 2)
hours, minutes = divmod(total_minutes, 60)

3. Comparison and Chaining

0 < x < 10              # True iff 0 < x AND x < 10
a == b == c             # True iff a == b AND b == c
0 <= i < len(xs)        # idiomatic bounds check
  • Each operand evaluated once
  • C++ has no equivalent, 0 < x < 10 there is (0 < x) < 10 (bool compared to int)
  • ==/!= work between unlike numerics (1 == 1.0 is True)
  • Ordering between unrelated types (1 < "a") raises TypeError

4. Bit Operators

Op Meaning
& bitwise AND
| bitwise OR
^ bitwise XOR
~ bitwise NOT
<< left shift
>> arithmetic right shift (sign-preserving)
0b1100 & 0b1010    # 8  (0b1000)
0b1100 | 0b1010    # 14 (0b1110)
~5                 # -6  (two's-complement view of an arbitrary-precision int)
5 << 2             # 20
20 >> 2            # 5

n.bit_length()     # number of bits required (5 for 16)
n.bit_count()      # number of 1 bits (3.10+)
  • No unsigned; no shift overflow (int is arbitrary precision)
  • >> on negatives sign-extends (same as C++ signed >>, but standardized)

5. math and cmath

import math
math.sqrt(2)         # 1.4142135623730951
math.pi              # 3.141592653589793
math.tau             # 2 * pi
math.inf             # float('inf')
math.nan
math.log(8, 2)       # 3.0
math.log2(8)         # 3.0
math.gcd(12, 18)     # 6
math.factorial(10)   # 3628800
math.isnan(x)        # NaN check
math.isclose(a, b)   # approximate equality
  • cmath provides the same functions for complex arguments

6. decimal and fractions

  • For exact decimal arithmetic (money, taxes), binary floats can't represent 0.1 exactly
from decimal import Decimal, getcontext
getcontext().prec = 10
Decimal("0.1") + Decimal("0.2")    # Decimal('0.3')

from fractions import Fraction
Fraction(1, 3) + Fraction(1, 6)    # Fraction(1, 2)
  • Avoid Decimal(0.1), captures the float's imprecision
  • Always pass a string: Decimal("0.1")