Foundations — numeric precision, validation and complexity — DedSec Project
Foundations — numeric precision, validation and complexity Numeric precision and money Problem and mental model Binary floats cannot exactly represent every decimal fraction. Repeated…
Numeric precision and money
Problem and mental model
Binary floats cannot exactly represent every decimal fraction. Repeated rounding can produce totals that differ from legal or business expectations. Decide whether to use integer cents or Decimal with a documented rounding mode; never assume a formatted display string is suitable for further calculations.
Reproducible illustration
from decimal import Decimal, ROUND_HALF_UP
price = Decimal('19.99')
vat = Decimal('0.24')
total = (price * (1 + vat)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
assert total == Decimal('24.79')
print(total)
Independent validation
Expected output: 24.79. Try three invoice lines and compare rounding each line with rounding at the final total. Test negative adjustments, quantity zero, and a currency with a different minor-unit convention. Document why your policy is reproducible.
Authoritative documentation: https://docs.python.org/3/library/decimal.html
Parsing and validation
Design principle and reasoning
Parsing turns text into structured values; validation determines whether those values satisfy domain rules. A syntactically valid JSON object may contain negative counts or unexpected keys.
Study a concrete case
import json
obj=json.loads('{"count":4}')
if set(obj)!={'count'} or type(obj['count']) is not int or obj['count']<0:raise ValueError()
assert obj['count']==4
Independent exercise
Change JSON to a list, string count, boolean count and extra key. Separate JSONDecodeError from schema error.
Evidence for review
For Parsing and validation, identify one failure mode beyond the happy path and specify a test or observation that would expose it. Write the expected result first, then validate the exact boundary without altering a production environment.
Time complexity
Mechanism and scope
Time complexity describes operation count as input size grows, not guaranteed milliseconds. Linear scan visits at most n items; nested full scans do n² comparisons. For small n, cache effects and setup can dominate.
Implementation example
def pair_count(n):
return sum(1 for i in range(n) for j in range(n))
assert pair_count(10)==100
Reproduce and investigate
Measure n=50,100,200 and count iterations rather than relying only on wall time. Compare growth factors with a one-loop function; account for measurement noise.
Evidence to record
For Time complexity, document the exact input that changes this outcome, the operation responsible for the change, and one falsifying test. Measure memory or timing only where it changes the claim, and do not treat a successful demonstration as a proof for every input.
Space complexity
Mechanism and scope
Space complexity measures auxiliary memory relative to input size. Creating a full transformed list consumes O(n) extra space; yielding one transformed item at a time can have O(1) generator state when the consumer is streaming.
Implementation example
def squares(values):
for n in values: yield n*n
assert list(squares(range(4)))==[0,1,4,9]
Reproduce and investigate
Contrast list(squares(range(n))) against sum(squares(range(n))) and measure memory. A generator does not save memory if it is immediately materialized.
Evidence to record
For Space complexity, document the exact input that changes this outcome, the operation responsible for the change, and one falsifying test. Measure memory or timing only where it changes the claim, and do not treat a successful demonstration as a proof for every input.