Ei vielä käännetty
Tätä sivua ei ole vielä käännetty suomeksi, joten se näytetään englanniksi. Auta kääntämään
decimal Module Complexity¶
The decimal module provides support for decimal floating point arithmetic with arbitrary precision, avoiding binary floating point rounding errors.
Complexity Reference¶
| Operation | Time | Space | Notes |
|---|---|---|---|
Decimal(value) |
O(n) | O(n) | n = digits in value |
Decimal.from_float(f) |
O(1) | O(1) | Convert from float |
Decimal.from_number(x) |
O(n) | O(n) | Convert from int/float/Decimal |
| Addition/Subtraction | O(n) | O(n) | n = max digits |
| Multiplication | O(n²) | O(n) | Grade-school; Python uses Karatsuba for large n |
| Division | O(n²) | O(n) | Long division algorithm |
quantize() |
O(n) | O(n) | Round to precision |
normalize() |
O(n) | O(n) | Remove trailing zeros |
sqrt() |
O(n²) | O(n) | Square root |
exp() / ln() / log10() |
O(n²) | O(n) | Transcendental functions |
Comparison (compare()) |
O(n) | O(1) | n = digits to compare |
compare_total() |
O(n) | O(1) | Compare with total ordering |
as_tuple() |
O(n) | O(n) | Return (sign, digits, exponent) |
as_integer_ratio() |
O(n) | O(n) | Return (numerator, denominator) |
to_eng_string() |
O(n) | O(n) | Engineering notation string |
to_integral_value() |
O(n) | O(n) | Round to integer |
copy_abs() / copy_negate() |
O(n) | O(n) | Copy with sign change |
copy_sign(other) |
O(n) | O(n) | Copy with other's sign |
is_finite() / is_infinite() |
O(1) | O(1) | Check special values |
is_nan() / is_qnan() / is_snan() |
O(1) | O(1) | Check NaN types |
is_signed() / is_zero() |
O(1) | O(1) | Check sign/zero |
is_normal() / is_subnormal() |
O(1) | O(1) | Check normalization |
number_class() |
O(1) | O(1) | Return classification string |
adjusted() |
O(1) | O(1) | Return adjusted exponent |
radix() |
O(1) | O(1) | Return 10 (base) |
same_quantum(other) |
O(1) | O(1) | Check same exponent |
scaleb(exp) |
O(n) | O(n) | Scale by power of 10 |
shift(n) / rotate(n) |
O(n) | O(n) | Shift/rotate digits |
logical_and/or/xor/invert |
O(n) | O(n) | Logical ops on digit strings |
fma(x, y) |
O(n²) | O(n) | Fused multiply-add |
max(other) / min(other) |
O(n) | O(1) | Return max/min |
next_plus() / next_minus() |
O(n) | O(n) | Next representable value |
next_toward(other) |
O(n) | O(n) | Next value toward other |
remainder_near(other) |
O(n²) | O(n) | IEEE remainder |
getcontext() |
O(1) | O(1) | Get current context |
setcontext(ctx) |
O(1) | O(1) | Set current context |
localcontext([ctx]) |
O(1) | O(1) | Context manager |
Context() |
O(1) | O(1) | Create context |
DecimalTuple |
O(1) | O(1) | Tuple of sign/digits/exponent |
DefaultContext / BasicContext / ExtendedContext |
O(1) | O(1) | Predefined contexts |
IEEEContext() |
O(1) | O(1) | IEEE 754 context |
| Signals/flags | O(1) | O(1) | Inexact, Rounded, Underflow, Overflow, Subnormal, Clamped |
| Exceptions | O(1) | O(1) | DecimalException, InvalidOperation, DivisionByZero, etc. |
| Rounding modes | O(1) | O(1) | ROUND_HALF_EVEN, ROUND_UP, etc. |
| Limits | O(1) | O(1) | MAX_PREC, MAX_EMAX, MIN_EMIN, MIN_ETINY |
Creating Decimal Objects¶
Basic Creation¶
from decimal import Decimal
# Create from string - O(n) where n = string length
d1 = Decimal('3.14') # O(4)
d2 = Decimal('0.1') # O(3)
d3 = Decimal('123456') # O(6)
# Create from integer - O(n)
d4 = Decimal(42) # O(2)
# Create from float (caution) - O(1)
d5 = Decimal(0.1) # O(1) but inaccurate!
# Result: Decimal('0.1000000000000000055511151231257827021181583404541015625')
Why Not Floats?¶
from decimal import Decimal
# Float rounding error
print(0.1 + 0.2) # 0.30000000000000004
# Decimal avoids this - O(n) for each operation
d1 = Decimal('0.1')
d2 = Decimal('0.2')
result = d1 + d2 # O(1 + 1) = O(1) - perfect precision
# Result: Decimal('0.3')
Arithmetic Operations¶
Basic Operations¶
from decimal import Decimal
# Addition - O(n) where n = max digits
a = Decimal('10.5')
b = Decimal('20.3')
result = a + b # Decimal('30.8') - O(4)
# Subtraction - O(n)
result = b - a # Decimal('9.8') - O(4)
# Multiplication - O(n²) for grade-school multiply
a = Decimal('123') # 3 digits
b = Decimal('456') # 3 digits
result = a * b # O(9) - quadratic
# Result: Decimal('56088')
# Division - O(n²)
a = Decimal('100')
b = Decimal('3')
result = a / b # O(n²) where n = precision
# Result: Decimal('33.33333333333333333333333333')
Setting Precision¶
from decimal import Decimal, getcontext
# Get current context
ctx = getcontext()
print(ctx.prec) # Default: 28 digits
# Set precision - affects all operations
ctx.prec = 10
# Now operations use 10 digits - O(n)
result = Decimal('1') / Decimal('3')
print(result) # Decimal('0.3333333333')
# Restore
ctx.prec = 28
Common Operations¶
Rounding¶
from decimal import Decimal, ROUND_HALF_UP
# Create decimal
d = Decimal('2.675')
# Quantize to 2 decimal places - O(n)
rounded = d.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
# Result: Decimal('2.68')
# Different rounding modes
from decimal import ROUND_DOWN, ROUND_UP, ROUND_CEILING, ROUND_FLOOR
d.quantize(Decimal('0.01'), rounding=ROUND_DOWN) # 2.67
d.quantize(Decimal('0.01'), rounding=ROUND_UP) # 2.68
d.quantize(Decimal('0.01'), rounding=ROUND_CEILING) # 2.68
d.quantize(Decimal('0.01'), rounding=ROUND_FLOOR) # 2.67
String Formatting¶
from decimal import Decimal
# Format decimal - O(n)
d = Decimal('3.14159265')
# Using format() - O(n)
formatted = format(d, '.2f') # '3.14' - O(4)
# Using f-string - O(n)
formatted = f"{d:.2f}" # '3.14'
# As string - O(n)
s = str(d) # '3.14159265'
Money Calculations¶
from decimal import Decimal, ROUND_HALF_UP
# Prices with Decimal
price = Decimal('19.99')
quantity = 3
# Multiplication - O(n²)
total = price * quantity # Decimal('59.97')
# Tax calculation - O(n²)
tax_rate = Decimal('0.08')
tax = (total * tax_rate).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
# tax = Decimal('4.80')
final = total + tax
# final = Decimal('64.77')
Performance Considerations¶
Decimal vs Float¶
import time
from decimal import Decimal
# Float operations (fast but imprecise)
start = time.time()
result = 0.0
for _ in range(100000):
result += 0.1
end = time.time()
print(f"Float time: {end - start}") # Very fast
print(result) # 10000.000000000002
# Decimal operations (slower but precise)
start = time.time()
result = Decimal('0')
for _ in range(100000):
result += Decimal('0.1')
end = time.time()
print(f"Decimal time: {end - start}") # Slower - O(n²)
print(result) # Decimal('10000')
Precision Impact¶
from decimal import Decimal, getcontext
# Higher precision = slower operations
ctx = getcontext()
# Low precision (faster)
ctx.prec = 10
result = Decimal('1') / Decimal('3') # O(10)
# High precision (slower)
ctx.prec = 100
result = Decimal('1') / Decimal('3') # O(100)
# Each digit added increases computation
Caching Decimals¶
from decimal import Decimal
# Pre-compute common values - O(n) once
TAX_RATE = Decimal('0.08')
SHIPPING = Decimal('5.99')
DISCOUNT = Decimal('0.10')
# Reuse in loop - O(n) per operation, not O(n²)
prices = [Decimal(str(p)) for p in [10, 20, 30]]
for price in prices:
total = price * (1 - DISCOUNT) + SHIPPING # O(n)
# Use tax_rate
Comparisons¶
from decimal import Decimal
# Equality - O(n) where n = digits
a = Decimal('10.00')
b = Decimal('10.0')
a == b # True - O(4)
# Less than - O(n)
a < b # False - O(4)
# Comparison with string (must convert) - O(n)
a == Decimal('10') # True
# Comparison with float (works but imprecise)
a == 10.0 # True (generally, but be careful)
Context Management¶
Local Context¶
from decimal import Decimal, localcontext
# Global precision
getcontext().prec = 28
with localcontext() as ctx:
# Local precision change
ctx.prec = 10
result = Decimal('1') / Decimal('3') # O(10)
print(result) # Decimal('0.3333333333')
# Global precision restored
result = Decimal('1') / Decimal('3')
print(result) # More digits - O(28)
Financial Calculations¶
Invoice Calculation¶
from decimal import Decimal, ROUND_HALF_UP, localcontext
def calculate_invoice(items, tax_rate):
"""Calculate invoice total with tax"""
with localcontext() as ctx:
ctx.prec = 10 # Sufficient for money
# Sum items - O(n * m) where n = items, m = digits
subtotal = sum((Decimal(str(price)) * qty for price, qty in items),
Decimal('0'))
# Apply tax - O(m)
tax = (subtotal * Decimal(str(tax_rate))).quantize(
Decimal('0.01'), rounding=ROUND_HALF_UP)
# Total - O(m)
total = (subtotal + tax).quantize(
Decimal('0.01'), rounding=ROUND_HALF_UP)
return subtotal, tax, total
# Usage - O(n * m)
items = [(19.99, 1), (5.50, 2), (100, 0.5)]
subtotal, tax, total = calculate_invoice(items, 0.08)
String Representations¶
from decimal import Decimal
d = Decimal('123.456')
# As string - O(n)
str(d) # '123.456'
# With engineering notation - O(n)
d.to_eng_string() # '123.456'
# As tuple (sign, digits, exponent) - O(1)
d.as_tuple() # DecimalTuple(sign=0, digits=(1,2,3,4,5,6), exponent=-3)
Special Values¶
from decimal import Decimal
# Special values
Decimal('Infinity') # Positive infinity
Decimal('-Infinity') # Negative infinity
Decimal('NaN') # Not a number
# Create from float
import math
Decimal(math.inf) # Decimal('Infinity')
# Operations with special values
d = Decimal('10')
d / Decimal('0') # Raises InvalidOperation
Decimal('Infinity') + 5 # Decimal('Infinity')
Decimal('NaN') + 5 # Decimal('NaN')
Version Notes¶
- Python 2.x: Decimal module available (limited support)
- Python 3.x: Full Decimal support with many rounding modes
- Python 3.8+: Improved performance and new operations
Related Modules¶
- fractions - Rational number arithmetic (exact but slower)
- math - Mathematical functions (uses floats)
- numbers - Numeric abstract base classes
Best Practices¶
✅ Do:
- Use Decimal for financial calculations (exact results)
- Create Decimal from strings, not floats
- Set appropriate precision for your domain
- Use
quantize()for rounding money - Cache common Decimal values
❌ Avoid:
- Mixing Decimal and float operations (convert both to Decimal)
- Creating Decimal from float:
Decimal(0.1)❌ useDecimal('0.1')✅ - Excessive precision (slower without benefit)
- Using Decimal for scientific computation (use float)
- Forgetting that multiplication is O(n²)