Simplify float conversion recipe.

This commit is contained in:
Raymond Hettinger 2008-02-07 20:09:43 +00:00
parent 65baa34115
commit 66cb7d4bd8
1 changed files with 15 additions and 25 deletions

View File

@ -1516,39 +1516,29 @@ Q. Is there a way to convert a regular float to a :class:`Decimal`?
A. Yes, all binary floating point numbers can be exactly expressed as a A. Yes, all binary floating point numbers can be exactly expressed as a
Decimal. An exact conversion may take more precision than intuition would Decimal. An exact conversion may take more precision than intuition would
suggest, so trapping :const:`Inexact` will signal a need for more precision:: suggest, so we trap :const:`Inexact` to signal a need for more precision::
def floatToDecimal(f): def float_to_decimal(f):
"Convert a floating point number to a Decimal with no loss of information" "Convert a floating point number to a Decimal with no loss of information"
# Transform (exactly) a float to a mantissa (0.5 <= abs(m) < 1.0) and an n, d = f.as_integer_ratio()
# exponent. Double the mantissa until it is an integer. Use the integer with localcontext() as ctx:
# mantissa and exponent to compute an equivalent Decimal. If this cannot ctx.traps[Inexact] = True
# be done exactly, then retry with more precision. while True:
try:
return Decimal(n) / Decimal(d)
except Inexact:
ctx.prec += 1
mantissa, exponent = math.frexp(f) >>> float_to_decimal(math.pi)
while mantissa != int(mantissa): Decimal("3.141592653589793115997963468544185161590576171875")
mantissa *= 2.0
exponent -= 1
mantissa = int(mantissa)
oldcontext = getcontext() Q. Why isn't the :func:`float_to_decimal` routine included in the module?
setcontext(Context(traps=[Inexact]))
try:
while True:
try:
return mantissa * Decimal(2) ** exponent
except Inexact:
getcontext().prec += 1
finally:
setcontext(oldcontext)
Q. Why isn't the :func:`floatToDecimal` routine included in the module?
A. There is some question about whether it is advisable to mix binary and A. There is some question about whether it is advisable to mix binary and
decimal floating point. Also, its use requires some care to avoid the decimal floating point. Also, its use requires some care to avoid the
representation issues associated with binary floating point:: representation issues associated with binary floating point::
>>> floatToDecimal(1.1) >>> float_to_decimal(1.1)
Decimal("1.100000000000000088817841970012523233890533447265625") Decimal("1.100000000000000088817841970012523233890533447265625")
Q. Within a complex calculation, how can I make sure that I haven't gotten a Q. Within a complex calculation, how can I make sure that I haven't gotten a