summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2008-02-07 20:09:43 (GMT)
committerRaymond Hettinger <python@rcn.com>2008-02-07 20:09:43 (GMT)
commit66cb7d4bd8a832ab7f645ab3af23a8917c9d273d (patch)
tree640117aad217017c3ba84fa4334caab93e8cabe3
parent65baa34115476cd42d41af5ca01c58226caab255 (diff)
downloadcpython-66cb7d4bd8a832ab7f645ab3af23a8917c9d273d.zip
cpython-66cb7d4bd8a832ab7f645ab3af23a8917c9d273d.tar.gz
cpython-66cb7d4bd8a832ab7f645ab3af23a8917c9d273d.tar.bz2
Simplify float conversion recipe.
-rw-r--r--Doc/library/decimal.rst46
1 files changed, 18 insertions, 28 deletions
diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst
index f59689f..3c3e613 100644
--- a/Doc/library/decimal.rst
+++ b/Doc/library/decimal.rst
@@ -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
Decimal. An exact conversion may take more precision than intuition would
-suggest, so trapping :const:`Inexact` will signal a need for more precision::
-
- def floatToDecimal(f):
- "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
- # exponent. Double the mantissa until it is an integer. Use the integer
- # mantissa and exponent to compute an equivalent Decimal. If this cannot
- # be done exactly, then retry with more precision.
-
- mantissa, exponent = math.frexp(f)
- while mantissa != int(mantissa):
- mantissa *= 2.0
- exponent -= 1
- mantissa = int(mantissa)
-
- oldcontext = getcontext()
- 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?
+suggest, so we trap :const:`Inexact` to signal a need for more precision::
+
+ def float_to_decimal(f):
+ "Convert a floating point number to a Decimal with no loss of information"
+ n, d = f.as_integer_ratio()
+ with localcontext() as ctx:
+ ctx.traps[Inexact] = True
+ while True:
+ try:
+ return Decimal(n) / Decimal(d)
+ except Inexact:
+ ctx.prec += 1
+
+ >>> float_to_decimal(math.pi)
+ Decimal("3.141592653589793115997963468544185161590576171875")
+
+Q. Why isn't the :func:`float_to_decimal` routine included in the module?
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
representation issues associated with binary floating point::
- >>> floatToDecimal(1.1)
+ >>> float_to_decimal(1.1)
Decimal("1.100000000000000088817841970012523233890533447265625")
Q. Within a complex calculation, how can I make sure that I haven't gotten a