Comparing float and decimal
Nick Craig-Wood
nick at craig-wood.com
Thu Sep 25 06:30:02 EDT 2008
Tim Roberts <timr at probo.com> wrote:
> Marc 'BlackJack' Rintsch <bj_666 at gmx.net> wrote:
> >
> >On Tue, 23 Sep 2008 07:08:07 -0700, Michael Palmer wrote:
> >
> >>> > This seems to break the rule that if A is equal to B and B is equal
> >>> > to C then A is equal to C.
> >>>
> >>> I don't see why transitivity should apply to Python objects in general.
> >>
> >> Well, for numbers it surely would be a nice touch, wouldn't it. May be
> >> the reason for Decimal to accept float arguments is that irrational
> >> numbers or very long rational numbers cannot be converted to a Decimal
> >> without rounding error, and Decimal doesn't want any part of it. Seems
> >> pointless to me, though.
> >
> >Is 0.1 a very long number? Would you expect ``0.1 == Decimal('0.1')`` to
> >be `True` or `False` given that 0.1 actually is
> >
> >In [98]: '%.50f' % 0.1
> >Out[98]: '0.10000000000000000555111512312578270211815834045410'
> >?
>
> Actually, it's not. Your C run-time library is generating random digits
> after it runs out of useful information (which is the first 16 or 17
> digits). 0.1 in an IEEE 784 double is this:
>
> 0.100000000000000088817841970012523233890533447265625
Not according to the decimal FAQ
http://docs.python.org/lib/decimal-faq.html
------------------------------------------------------------
import math
from decimal import *
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)
print "float(0.1) is", floatToDecimal(0.1)
------------------------------------------------------------
Prints this
float(0.1) is 0.1000000000000000055511151231257827021181583404541015625
On my platform
Python 2.5.2 (r252:60911, Aug 8 2008, 09:22:44),
[GCC 4.3.1] on linux2
Linux 2.6.26-1-686
Intel(R) Core(TM)2 CPU T7200
--
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick
More information about the Python-list
mailing list