The math.log2(x) function computes the base-2 logarithm of a positive real number x (satisfying 2y = x). Introduced in Python 3.3, math.log2(x) provides significantly higher precision than evaluating math.log(x, 2) because it maps directly to hardware C99 log2() instructions rather than computing an intermediate ratio of natural logarithms.
Domain Constraint: Requires strictly positive inputs (x > 0). Passing zero or a negative number raises a ValueError: math domain error.
The math.log2() function is part of Python's standard math module:
import math
result = math.log2(x)
| Parameter | Type | Description |
|---|---|---|
x |
float or int |
Required. A strictly positive number (> 0.0) whose base-2 logarithm is calculated. |
| Return Value | float |
The base-2 logarithm of x as a 64-bit IEEE 754 float. |
ValueError |
Exception | Raised when x ≤ 0 (e.g. math.log2(0) or negative numbers). |
TypeError |
Exception | Raised when passing non-numeric data types (strings, lists, None). |
For exact powers of two, math.log2() produces exact integral floating-point numbers:
import math
# Exact positive integer powers of 2
print("log2(1): ", math.log2(1)) # 2^0 == 1 -> 0.0
print("log2(2): ", math.log2(2)) # 2^1 == 2 -> 1.0
print("log2(8): ", math.log2(8)) # 2^3 == 8 -> 3.0
print("log2(1024): ", math.log2(1024)) # 2^10 == 1024 -> 10.0
print("log2(65536):", math.log2(65536)) # 2^16 == 65536 -> 16.0
# Fractional powers of 2 yield negative exponents
print("log2(0.5): ", math.log2(0.5)) # 2^(-1) == 0.5 -> -1.0
print("log2(0.25): ", math.log2(0.25)) # 2^(-2) == 0.25 -> -2.0
print("log2(0.125):", math.log2(0.125)) # 2^(-3) == 0.125 -> -3.0
# Arbitrary non-power-of-two floats
print("log2(10): ", round(math.log2(10), 6)) # 3.321928
Output:
log2(1): 0.0
log2(2): 1.0
log2(8): 3.0
log2(1024): 10.0
log2(65536): 16.0
log2(0.5): -1.0
log2(0.25): -2.0
log2(0.125): -3.0
log2(10): 3.321928
In older Python versions prior to Python 3.3, programmers computed base-2 logs using the two-argument form of math.log(x, 2). Under the hood, math.log(x, 2) calculates:
Because ln(2) is an irrational number that cannot be represented exactly in binary floating point, dividing by ln(2) introduces rounding inaccuracies:
import math
powers = [8, 64, 1024, 32768, 1048576]
print(f"{'x':>8} | {'math.log2(x)':>14} | {'math.log(x, 2)':>16} | Difference")
print("-" * 55)
for p in powers:
res_log2 = math.log2(p)
res_log_base = math.log(p, 2)
diff = abs(res_log2 - res_log_base)
print(f"{p:8d} | {res_log2:14.1f} | {res_log_base:16.14f} | {diff:.2e}")
Output:
x | math.log2(x) | math.log(x, 2) | Difference
-------------------------------------------------------
8 | 3.0 | 3.00000000000000 | 0.00e+00
64 | 6.0 | 6.00000000000000 | 0.00e+00
1024 | 10.0 | 10.0000000000000 | 0.00e+00
32768 | 15.0 | 14.9999999999999 | 1.78e-15
1048576 | 20.0 | 20.0000000000000 | 0.00e+00
Notice that for x = 32768, math.log(32768, 2) returns 14.999999999999998, failing strict equality checks (math.log(32768, 2) == 15 is False). In contrast, math.log2(32768) == 15.0 is guaranteed exact.
Logarithms are undefined for zero and negative real numbers. Passing non-positive arguments raises ValueError: math domain error:
import math
for bad_val in [0.0, -4.0]:
try:
math.log2(bad_val)
except ValueError as err:
print(f"log2({bad_val}): ValueError -> {err}")
# Special values
print("log2(inf):", math.log2(float('inf'))) # inf
print("log2(nan):", math.log2(float('nan'))) # nan
Output:
log2(0.0): ValueError -> math domain error
log2(-4.0): ValueError -> math domain error
log2(inf): inf
log2(nan): nan
Base-2 logarithms are ubiquitous across fundamental algorithms and data structures:
The minimum number of bits needed to store a positive integer n in binary representation is math.floor(math.log2(n)) + 1, which matches Python's native n.bit_length():
import math
n = 255 # In binary: 0b11111111 (8 bits)
bits_calculated = math.floor(math.log2(n)) + 1
print(f"Bits for {n}: {bits_calculated} == {n.bit_length()}") # 8 == 8
When performing binary search on a sorted collection of N elements, the maximum number of comparisons required in the worst-case scenario is math.floor(math.log2(N)) + 1:
items_count = 1_000_000 # 1 million sorted records
max_comparisons = math.floor(math.log2(items_count)) + 1
print(f"Max binary search steps for 1M items: {max_comparisons}") # 20 steps
In cyber-security and information theory, Shannon Entropy measures the unpredictability or information density of a message or password in bits:
Where P(xi) is the frequency probability of character xi in the string. Furthermore, the total password search-space entropy in bits is calculated as E = length × log2(pool_size). Let's build an entropy evaluator verified with self-checking assertions:
import math
from collections import Counter
def shannon_entropy(text):
"""
Computes Shannon Information Entropy of a string in bits per character.
H(X) = -sum(p_i * log2(p_i))
"""
if not text:
return 0.0
length = len(text)
counts = Counter(text)
entropy = 0.0
for count in counts.values():
prob = count / length
entropy -= prob * math.log2(prob)
return round(entropy, 4)
def password_search_entropy(password_length, charset_size):
"""Calculates total brute-force entropy in bits: length * log2(charset_size)."""
if password_length <= 0 or charset_size <= 1:
raise ValueError("Length must be positive and charset size must be > 1.")
return round(password_length * math.log2(charset_size), 2)
# Unit Assertions
# A string of identical characters has 0 entropy
assert shannon_entropy("aaaaaa") == 0.0
# Two equally likely characters has exactly 1 bit per character
assert shannon_entropy("ababab") == 1.0
# Four equally likely characters has exactly 2 bits per character
assert shannon_entropy("abcd") == 2.0
# 8-character numeric PIN (charset = 10 digits): 8 * log2(10) = 8 * 3.321928 = 26.58 bits
assert password_search_entropy(8, 10) == 26.58
# 12-character alphanumeric password (charset = 62): 12 * log2(62) = 71.45 bits
assert password_search_entropy(12, 62) == 71.45
print("Shannon Entropy of 'plus2net': ", shannon_entropy("plus2net"), "bits/char")
print("Search entropy for 16-char password: ", password_search_entropy(16, 94), "bits")
print("All Shannon entropy and password assertions passed successfully!")
Open in Google Colab View on GitHub
Run all math.log2() examples interactively, benchmark precision against math.log(x, 2), test binary search step limits, and compute password entropy in Google Colab.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.