Loading...
Choose decimal arithmetic deliberately, construct values from the intended input and distinguish arithmetic precision from the number of places printed.
What you'll be able to do
Python’s ordinary float uses a binary floating-point representation on typical supported platforms. Decimal supports decimal floating-point arithmetic, so Decimal("0.1") stores the intended decimal tenth exactly. Decimal(0.1) instead converts the existing binary approximation to a decimal value. Changing the destination type cannot undo information already lost in the source.
Construct a decimal measurement from its original text where possible. Keep arithmetic operands compatible: adding a float directly to a Decimal is not a reliable conversion policy and normally raises TypeError. Choose the representation at the input boundary and keep it consistent throughout a calculation, rather than mixing float and Decimal in different branches.
The decimal context’s precision is a count of significant digits used by arithmetic, not a command to print every result with that many places after the decimal point. With precision 5, Decimal(1)/Decimal(7) gives 0.14286. A Decimal constructed from text can retain more digits than the arithmetic context; the context affects subsequent operations. localcontext lets this example change precision without changing unrelated code’s global context.
round(value, 2) rounds a Decimal to two fractional places using the relevant context rounding policy. Under ROUND_HALF_EVEN, 2.345 becomes 2.34 and 2.355 becomes 2.36. Specify the required policy instead of assuming that every tie must round upwards. To compare finite Decimals, ordinary comparisons work; a.compare(b) returns Decimal(-1), Decimal(0) or Decimal(1). Use the real Decimal method rather than inventing a module-level decimal.compare function.
from decimal import Decimal, localcontext, ROUND_HALF_EVEN
with localcontext() as context:
context.prec = 5
context.rounding = ROUND_HALF_EVEN
print(Decimal(1) / Decimal(7))
print(round(Decimal('2.345'), 2))
print(round(Decimal('2.355'), 2))
print(Decimal('1.20').compare(Decimal('1.2')))Scroll horizontally to see the full code or table.Decimal text parsing can raise InvalidOperation for malformed input. However, strings such as NaN and Infinity are valid Decimal syntax and may still be invalid for a measurement. The parser below accepts text representing a finite value in the inclusive interval 0 to 100. It strips surrounding whitespace, catches malformed numeric input and explicitly rejects non-finite or out-of-range values.
Its ValueError is a documented input failure, allowing the caller to display a useful message or request another reading. Do not catch every exception around the entire program: an unrelated programming defect should not be relabelled as bad user input. Test both endpoints, a typical fraction, negative input, a value just above 100, an empty string and special values. These localcontext/is_finite details support robust practice beyond simply memorising the subset’s names.
from decimal import Decimal, InvalidOperation
def parse_percentage(text):
"""Return a finite Decimal in [0, 100] from text; otherwise raise ValueError."""
try:
value = Decimal(text.strip())
except InvalidOperation as error:
raise ValueError('Enter a decimal percentage') from error
if not value.is_finite() or not Decimal(0) <= value <= Decimal(100):
raise ValueError('Percentage must be finite and between 0 and 100')
return value
for text in (' 12.50 ', '0', '100', 'NaN', '100.01', 'oops'):
try:
print(parse_percentage(text))
except ValueError:
print('invalid')Scroll horizontally to see the full code or table.Attempt the task before opening its worked response. Record each change of state, explain the rule used, and check the result against the original requirements. Code examples labelled Python 3 use that language’s conventions; pseudocode states its own assumptions.
Common mistakes to avoid
Key takeaways
Test yourself
Answer a few questions, then review anything you missed.
Start with the quiz above to check the key ideas. You can also choose another topic from the practice library.