mirror of https://github.com/python/cpython
Simplify float conversion recipe.
This commit is contained in:
parent
65baa34115
commit
66cb7d4bd8
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue