On Sun, 23 May 2010 12:19:07 am Wayne Werner wrote: > On Sat, May 22, 2010 at 7:32 AM, Steven D'Aprano <st...@pearwood.info>wrote: > > Why do people keep recommending Decimal? Decimals suffer from the > > exact same issues as floats, > > This is exactly incorrect! The Decimal operator offers /exact/ > decimal point operations.
Decimal is only exact for fractions which can be represented by a finite sum of powers-of-ten, like 0.1, just like floats can only represent fractions exactly if they can be represented by a finite sum of powers-of-two, like 0.5. Not only did I demonstrate an example of rounding error using Decimal in my post, but you then repeated that rounding error and then had the audacity to claim that it was "exact": > For an example about the exactness of Decimal v Float: > >>> d = Decimal(1)/Decimal(3) > >>> d > > Decimal('0.3333333333333333333333333333') > > >>> d*Decimal(3) > > Decimal('0.9999999999999999999999999999') Does that look like exactly one to you? I don't know what they taught you, but when I was in school, I learned that one was exactly 1, not 0.9 or 0.999 or even 0.9999999999999999999999999999. But don't believe five hundred years of mathematics, do the test yourself: >>> d*Decimal(3) == 1 False We can calculate the exact error: >>> d = Decimal(1)/Decimal(3) >>> 1 - d*Decimal(3) == 0 False >>> 1 - d*Decimal(3) Decimal('1E-28') Small, but not zero. And adding more precision isn't the answer: it will make the error smaller, true enough, but not zero: >>> decimal.getcontext().prec = 100 >>> d = Decimal(1)/Decimal(3) >>> d*Decimal(3) == 1 False >>> 1 - d*Decimal(3) Decimal('1E-100') To get that error to zero exactly, you need an infinite precision. > They implement non-hardware operations to > preserve exactness. For more information on exactly what and how the > decimal module does what it does, see the following: > > http://docs.python.org/library/decimal.html I know what the decimal module does. It is capable of representing *decimal* numbers exactly, but not all fractions are exact decimal numbers, just as not all fractions are exact binary numbers. For exact fractions, you need the fractions module. > plus they are slower. > > > Because if memory serves correctly the Python implementation uses > serial arithmetic, rather than the hardware implementation of > floating point calculations. I don't understand what you mean by serial arithmetic, but the reason the decimal module is slow is that it is currently written in pure Python. A C version would be faster (but still slower than the hardware implementation of float calculations). > Please stop propagating myths about the Decimal module. I'm not. You are misrepresenting Decimal as a panacea for all rounding issues, which it is not. > >>> d = 1/3.0 > >>> d*3 > 1.0 Curiously, floats perform that specific calculation better than Decimal. That shows that sometimes you can have *too much* precision for a calculation. float rounds off the answer after just 17 decimal places (by memory), giving exactly 1, while Decimal (by default) rounds to 28 places, leading to an error. Of course, there are other calculations where Decimal is more accurate: >>> sum(0.1 for i in range(10)) == 1 False >>> sum(Decimal('0.1') for i in range(10)) == 1 True This is only to be expected, because 0.1 is an exact power of ten, but not an exact power of two. -- Steven D'Aprano _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor