Skip to main content

Module floatpath

Module floatpath 

Source
Expand description

Port of base.py’s float/Decimal path: float2tuple and to_cardinal_float.

§Why the f64 arrives as an f64

The float branch of float2tuple is binary arithmetic:

post = abs(value - pre) * 10**precision
if abs(round(post) - post) < 0.01:
    post = int(round(post))
else:
    post = int(math.floor(post))

Those artefacts are load-bearing. 2.675 really does produce 674.9999999999998, and the < 0.01 heuristic is what rescues it back to 675. Re-deriving that from a decimal string would compute the right answer and therefore the wrong one. Python floats and Rust f64 are both IEEE-754 doubles, so passing the raw double across reproduces it exactly.

precision still comes from Python: it is abs(Decimal(str(value)) .as_tuple().exponent), which depends on repr(float) — shortest round-trip formatting that we deliberately do not reimplement.

§The one true rounding trap

Python’s round() is round-half-to-even (round(2.5) == 2), while Rust’s f64::round() is half-away-from-zero (2.5_f64.round() == 3.0). Every rounding here uses round_ties_even().

Enums§

FloatValue
The value handed to the float path, mirroring what Python’s dispatcher saw.

Functions§

cardinal_from_bigdecimal
Render a BigDecimal through the float path — the fractional-cents entry point. right is e.g. 65.3 cents, so its own scale is the precision.
default_to_cardinal_float
Python’s Num2Word_Base.to_cardinal_float.
float2tuple
Python’s Num2Word_Base.float2tuple. Returns (pre, post).
point_routed_float_entry
“Condition C” float routing — "." in str(value) decides. Most self-contained converters route on the value’s string form: visible decimals take the language’s float grammar even when the value is whole (5.0 -> “pět čárka nula”), plain ints don’t (Decimal(“5”) -> “pět”). Languages with this shape point their cardinal_float_entry here.