Welcome, guest | Sign In | My Account | Store | Cart

Evaluate using Decimals instead of floats.

Python, 18 lines
 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18``` ```import re number_pattern = re.compile(r"((\A|(?<=\W))(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)") def deciexpr(expr): """Substitute Decimals for floats in an expression string. >>> from decimal import Decimal >>> s = '+21.3e-5*85-.1234/81.6' >>> deciexpr(s) "+Decimal('21.3e-5')*Decimal('85')-Decimal('.1234')/Decimal('81.6')" >>> eval(s) 0.016592745098039215 >>> eval(deciexpr(s)) Decimal("0.01659274509803921568627450980") """ return number_pattern.sub(r"Decimal('\1')", expr) ```

The numeric part of the regular expression is a direct translation from the decimal module's docs for Decimal object. See section 2 at http://docs.python.org/lib/module-decimal.html

For clarity, the regular expression does not scan for NaNs and Infinities. Those are trivial to incorporate if necessary.

Note, the optional leading sign is excluded from the pattern -- this is consistent with what Python does for other numeric literals (-0.1 lexes as a unary minus operation on 0.1). See http://docs.python.org/ref/numbers.html

The token separator part of the regular expression assures that numbers either start at the beginning of the string or are preceded by a single non-alphanumeric character. This prevents spurious mistranslations of valid Python identifiers such as vec1, vec2, etc. Created by Raymond Hettinger on Tue, 29 Mar 2005 (PSF)