[Tutor] Float Numbers. 98/100 returns 0.97999999999999998

Tim Peters tim.one@home.com
Wed, 28 Mar 2001 02:19:58 -0500


[Remco Gerlich]
> Hmm, there is a small fixed decimal precision arithmetic library called
> FixedPoint that you probably want to use, see FixedPoint.py and
> .README in
> ftp://ftp.python.org/pub/python/contrib-09-Dec-1999/DataStructures/ .

[Jethro Cramp]
> Thanks for the info. I finally got around to trying to use FixedPoint
> today.  However when I tested it in the python interpreter I found
> some very weird results:
>
> >>> x = FixedPoint("5.55")
> >>> print x
> .05
>
> According to the docstrings the above should produce the result:
> >>> x = FixedPoint("5.55")  # precision defaults to 2
> >>> print x
> 5.55
>
> I am using Python 2.0. Could this be caused by differences between
> 1.5.2 and 2.0?

Yuck, yes.  For long (unbounded) integers i, str(i) *used* to produce the
letter "L" at the end, but by popular demand it no longer does.  That's how
you're getting burned here.  Replace this block of code:

    def __str__(self):
        n, p = self.n, self.p
        i, f = divmod(abs(n), _tento(p))
        if p:
            frac = str(f)[:-1]
            frac = "0" * (p - len(frac)) + frac
        else:
            frac = ""
        return "-"[:n<0] + \
               str(i)[:-1] + \
               "." + frac

with this:

    def __str__(self):
        n, p = self.n, self.p
        i, f = divmod(abs(n), _tento(p))
        if p:
            frac = str(f)
            frac = "0" * (p - len(frac)) + frac
        else:
            frac = ""
        return "-"[:n<0] + \
               str(i) + \
               "." + frac

(that simply gets rid of the two instances of [:-1], which stripped off the
old trailing "L" but are now deleting the last digit(!)), and all will be
well under 2.0.  Or, maybe better, replace it with this:

    def __str__(self):
        n, p = self.n, self.p
        i, f = divmod(abs(n), _tento(p))
        if p:
            frac = repr(f)[:-1]
            frac = "0" * (p - len(frac)) + frac
        else:
            frac = ""
        return "-"[:n<0] + \
               repr(i)[:-1] + \
               "." + frac

(replacing the original "str" calls with "repr" calls -- repr(long) still
produces an "L" at the end) and it should work fine under both.

Unfortunately, I don't know of any way to get the ftp site updated anymore --
it's just an archive of old code.