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