@@ -1516,39 +1516,29 @@ Q. Is there a way to convert a regular float to a :class:`Decimal`?
15161516
15171517A. Yes, all binary floating point numbers can be exactly expressed as a
15181518Decimal. An exact conversion may take more precision than intuition would
1519- suggest, so trapping :const: `Inexact ` will signal a need for more precision::
1520-
1521- def floatToDecimal(f):
1522- "Convert a floating point number to a Decimal with no loss of information"
1523- # Transform (exactly) a float to a mantissa (0.5 <= abs(m) < 1.0) and an
1524- # exponent. Double the mantissa until it is an integer. Use the integer
1525- # mantissa and exponent to compute an equivalent Decimal. If this cannot
1526- # be done exactly, then retry with more precision.
1527-
1528- mantissa, exponent = math.frexp(f)
1529- while mantissa != int(mantissa):
1530- mantissa *= 2.0
1531- exponent -= 1
1532- mantissa = int(mantissa)
1533-
1534- oldcontext = getcontext()
1535- setcontext(Context(traps=[Inexact]))
1536- try:
1537- while True:
1538- try:
1539- return mantissa * Decimal(2) ** exponent
1540- except Inexact:
1541- getcontext().prec += 1
1542- finally:
1543- setcontext(oldcontext)
1544-
1545- Q. Why isn't the :func: `floatToDecimal ` routine included in the module?
1519+ suggest, so we trap :const: `Inexact ` to signal a need for more precision::
1520+
1521+ def float_to_decimal(f):
1522+ "Convert a floating point number to a Decimal with no loss of information"
1523+ n, d = f.as_integer_ratio()
1524+ with localcontext() as ctx:
1525+ ctx.traps[Inexact] = True
1526+ while True:
1527+ try:
1528+ return Decimal(n) / Decimal(d)
1529+ except Inexact:
1530+ ctx.prec += 1
1531+
1532+ >>> float_to_decimal(math.pi)
1533+ Decimal("3.141592653589793115997963468544185161590576171875")
1534+
1535+ Q. Why isn't the :func: `float_to_decimal ` routine included in the module?
15461536
15471537A. There is some question about whether it is advisable to mix binary and
15481538decimal floating point. Also, its use requires some care to avoid the
15491539representation issues associated with binary floating point::
15501540
1551- >>> floatToDecimal (1.1)
1541+ >>> float_to_decimal (1.1)
15521542 Decimal("1.100000000000000088817841970012523233890533447265625")
15531543
15541544Q. Within a complex calculation, how can I make sure that I haven't gotten a
0 commit comments