3.2*2 is 9.6 ... or maybe it isn't?

8 views
Skip to first unread message

Bojan Sudarevic

unread,
Jun 25, 2009, 2:04:57 PM6/25/09
to
Hi,

I'm PHP developer and entirely new to Python. I installed it (version
2.5.2, from Debian repos) today on the persuasion of a friend, who is a
Python addict.

The first thing I typed into it was 3.2*3 (don't ask why I typed *that*,
I don*t know, I just did). And the answer wasn't 9.6.

Here it is:

>>> 3.2*3
9.6000000000000014

So I became curious...

>>> 3.21*3
9.629999999999999
>>> (3.2*3)*2
19.200000000000003
... and so on ...

After that I tried Windows version (3.1rc2), and...

>>> 3.2*3
9.600000000000001

I wasn't particularly good in math in school and university, but I'm
pretty sure that 3.2*3 is 9.6.

Cheers,
Bojan

Mark Dickinson

unread,
Jun 25, 2009, 2:19:22 PM6/25/09
to
On Jun 25, 7:04 pm, Bojan Sudarevic <bo...@sudarevic.com> wrote:
> Hi,
>
> I'm PHP developer and entirely new to Python. I installed it (version
> 2.5.2, from Debian repos) today on the persuasion of a friend, who is a
> Python addict.
>
> The first thing I typed into it was 3.2*3 (don't ask why I typed *that*,
> I don*t know, I just did). And the answer wasn't 9.6.
>
> [examples snipped]

Hi Bojan,

This is a FAQ. Take a look at:

http://docs.python.org/tutorial/floatingpoint.html

and let us know whether that explains things to your
satisfaction.

Mark

Tomasz Zieliński

unread,
Jun 25, 2009, 2:20:13 PM6/25/09
to
On 25 Cze, 20:04, Bojan Sudarevic <bo...@sudarevic.com> wrote:

>
> I wasn't particularly good in math in school and university, but I'm
> pretty sure that 3.2*3 is 9.6.
>

It's not math, it's floating point representation of numbers - and its
limited accuracy.
Type 9.6 and you'll get 9.5999999999999996

--
Tomasz Zielinski
http://pyconsultant.eu

Emile van Sebille

unread,
Jun 25, 2009, 2:29:32 PM6/25/09
to pytho...@python.org
On 6/25/2009 11:04 AM Bojan Sudarevic said...

<snip>

>>>> 3.2*3
> 9.600000000000001
>
> I wasn't particularly good in math in school and university, but I'm
> pretty sure that 3.2*3 is 9.6.

Yes -- in this world. But in the inner workings of computers, 3.2 isn't
accurately representable in binary. This is a faq.

ActivePython 2.6.2.2 (ActiveState Software Inc.) based on
Python 2.6.2 (r262:71600, Apr 21 2009, 15:05:37) [MSC v.1500 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 3.2
3.2000000000000002
>>>


Emile


Paul Rudin

unread,
Jun 25, 2009, 2:32:12 PM6/25/09
to
Bojan Sudarevic <bo...@sudarevic.com> writes:

This is almost certainly nothing to do with python per se, but the
floating point implementation of your hardware. Floating point
arithmetic on computers is not accurate to arbitrary precision. If you
want such precision use a library that supports it or make you own
translations to and from appropriate integer sums (but it's going to be
slower).

Mark Dickinson

unread,
Jun 25, 2009, 2:35:12 PM6/25/09
to
On Jun 25, 7:04 pm, Bojan Sudarevic <bo...@sudarevic.com> wrote:
> The first thing I typed into it was 3.2*3 (don't ask why I typed *that*,
> I don*t know, I just did). And the answer wasn't 9.6.

It looks like it's false in PHP too, by the way (not
that I know any PHP, so I could well be missing
something...)


bernoulli:py3k dickinsm$ php -a
Interactive mode enabled

<?
$a = 3.2*3;
$b = 9.6;
var_dump($a);
float(9.6)
var_dump($b);
float(9.6)
var_dump($a == $b);
bool(false)


Mark

Bojan Sudarevic

unread,
Jun 25, 2009, 2:37:59 PM6/25/09
to
In article <26be756e-5a0a-40cd-b9a2-133ce14ac7d7
@n30g2000vba.googlegroups.com>, dick...@gmail.com says...

> This is a FAQ. Take a look at:
>
> http://docs.python.org/tutorial/floatingpoint.html
>
> and let us know whether that explains things to your
> satisfaction.
>

Hi Mark,

Yes, that explains things to my satisfation. Now I'm embarrassed that I
didn't know that before.

Thanks,
Bojan

Michael Torrie

unread,
Jun 25, 2009, 2:41:13 PM6/25/09
to pytho...@python.org
Bojan Sudarevic wrote:
> The first thing I typed into it was 3.2*3 (don't ask why I typed *that*,
> I don*t know, I just did). And the answer wasn't 9.6.
>
> Here it is:
>
>>>> 3.2*3
> 9.6000000000000014

I'm surprised how often people encounter this and wonder about it. As I
began programming back in the day using C, this is just something I grew
up with (grudging acceptance).

I guess PHP artificially rounds the results or something to make it seem
like it's doing accurate calculations, which is a bit surprising to me.
We all know that IEEE floating point is a horribly inaccurate
representation, but I guess I'd rather have my language not hide that
fact from me. Maybe PHP is using BCD or something under the hood (slow
but accurate).

If you want accurate math, check out other types like what is in the
decimal module:

>>> import decimal
>>> a=decimal.Decimal('3.2')
>>> print a * 3
9.6

Robert Kern

unread,
Jun 25, 2009, 2:56:37 PM6/25/09
to pytho...@python.org
On 2009-06-25 13:41, Michael Torrie wrote:

> If you want accurate math, check out other types like what is in the
> decimal module:
>
>>>> import decimal
>>>> a=decimal.Decimal('3.2')
>>>> print a * 3
> 9.6

I wish people would stop representing decimal floating point arithmetic as "more
accurate" than binary floating point arithmetic. It isn't. Decimal floating
point arithmetic does have an extremely useful niche: where the inputs have
finite decimal representations and either the only operations are addition,
subtraction and multiplication (e.g. many accounting problems) OR there are
conventional rounding modes to follow (e.g. most of the other accounting problems).

In the former case, you can claim that decimal floating point is more accurate
*for those problems*. But as soon as you have a division operation, decimal
floating point has the same accuracy problems as binary floating point.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Mark Dickinson

unread,
Jun 25, 2009, 3:31:05 PM6/25/09
to
On Jun 25, 7:41 pm, Michael Torrie <torr...@gmail.com> wrote:
> I guess PHP artificially rounds the results or something to make it seem
> like it's doing accurate calculations, which is a bit surprising to me.

After a bit of experimentation on my machine, it *looks* as though PHP
is using the usual hardware floats internally (no big surprise there),
but implicit conversions to string use 14 significant digits. If
Python's repr used '%.14g' internally instead of '%.17g' then we'd see
pretty much the same thing in Python.

> We all know that IEEE floating point is a horribly inaccurate

> representation [...]

That's a bit extreme! Care to elaborate?

, but I guess I'd rather have my language not hide that
> fact from me.  Maybe PHP is using BCD or something under the hood (slow
> but accurate).
>
> If you want accurate math, check out other types like what is in the
> decimal module:

As Robert Kern already said, there really isn't any sense in which
decimal
floating-point is any more accurate than binary floating-point, except
that---somewhat tautologically---it's better at representing decimal
values exactly.

The converse isn't true, though, from a numerical perspective: there
are some interesting examples of bad things that can happen with
decimal floating-point but not with binary. For example, given any
two Python floats a and b, and assuming IEEE 754 arithmetic with
default rounding, it's always true that a <= (a+b)/2 <= b, provided
that a+b doesn't overflow. Not so for decimal floating-point:

>>> import decimal
>>> decimal.getcontext().prec = 6 # set working precision to 6 sig figs
>>> (decimal.Decimal('7.12346') + decimal.Decimal('7.12348'))/2
Decimal('7.12345')

Similarly, sqrt(x*x) == x is always true for a positive IEEE 754
double x (again
assuming the default roundTiesToEven rounding mode, and assuming that
x*x neither overflows nor underflows). But this property fails for
IEEE 754-compliant decimal floating-point.

Mark

Scott David Daniels

unread,
Jun 25, 2009, 7:43:33 PM6/25/09
to
Robert Kern wrote:
> ... I wish people would stop representing decimal floating point arithmetic
> as "more accurate" than binary floating point arithmetic. It isn't.
> Decimal floating point arithmetic does have an extremely useful niche:
> ...
Well, we don't actually have an arbitrary-precision, huge exponent
version of binary floating point. In that sense the Decimal floating
point beats it. Not that it would be too hard to have such a floating
point in Python (long for mantissa, int for exponent, ...), but we don't
in fact have such a module in place.

--Scott David Daniels
Scott....@Acm.Org

Robert Kern

unread,
Jun 25, 2009, 7:50:21 PM6/25/09
to pytho...@python.org
On 2009-06-25 18:43, Scott David Daniels wrote:
> Robert Kern wrote:
>> ... I wish people would stop representing decimal floating point
>> arithmetic as "more accurate" than binary floating point arithmetic.
>> It isn't. Decimal floating point arithmetic does have an extremely
>> useful niche: ...
> Well, we don't actually have an arbitrary-precision, huge exponent
> version of binary floating point.

You may not. I do.

http://code.google.com/p/mpmath/

Mensanator

unread,
Jun 25, 2009, 7:53:39 PM6/25/09
to

We have the gmpy module which can do arbitray precision floats.

>>> gmpy.pi(600)
mpf
('3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446e0',
600)

>
> --Scott David Daniels
> Scott.Dani...@Acm.Org

Aahz

unread,
Jun 25, 2009, 7:55:40 PM6/25/09
to
In article <q_2dnQkBe7yWl9nX...@pdx.net>,

Scott David Daniels <Scott....@Acm.Org> wrote:
>
>Well, we don't actually have an arbitrary-precision, huge exponent
>version of binary floating point.

gmpy?
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

"as long as we like the same operating system, things are cool." --piranha

Robert Kern

unread,
Jun 25, 2009, 8:07:37 PM6/25/09
to pytho...@python.org
On 2009-06-25 18:43, Scott David Daniels wrote:
> Robert Kern wrote:
>> ... I wish people would stop representing decimal floating point
>> arithmetic as "more accurate" than binary floating point arithmetic.
>> It isn't. Decimal floating point arithmetic does have an extremely
>> useful niche: ...
> Well, we don't actually have an arbitrary-precision, huge exponent
> version of binary floating point. In that sense the Decimal floating
> point beats it.

And while that's true, to a point, that isn't what Michael or the many others
are referring to when they claim that decimal is more accurate (without any
qualifiers). They are misunderstanding the causes and limitations of the example
"3.2 * 3 == 9.6". You can see a great example of this in the comparison between
new Cobra language and Python:

http://cobra-language.com/docs/python/

In that case, they have a fixed-precision decimal float from the underlying .NET
runtime but still making the claim that it is more accurate arithmetic. While
you may make (completely correct) claims that decimal.Decimal can be more
accurate because of its arbitrary precision capabilities, this is not the claim
others are making or the one I am arguing against.

Ulrich Eckhardt

unread,
Jun 26, 2009, 3:17:02 AM6/26/09
to
Robert Kern wrote:
> I wish people would stop representing decimal floating point arithmetic as
> "more accurate" than binary floating point arithmetic.

Those that failed, learned. You only see those that haven't learnt yet.

Dialog between two teachers:
T1: Oh those pupils, I told them hundred times! when will they learn?
T2: They did, but there's always new pupils.

TGIF

Uli
(wave and smile)

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

Steven D'Aprano

unread,
Jun 26, 2009, 6:01:52 AM6/26/09
to
On Thu, 25 Jun 2009 12:41:13 -0600, Michael Torrie wrote:

> If you want accurate math, check out other types like what is in the
> decimal module:
>
>>>> import decimal
>>>> a=decimal.Decimal('3.2')
>>>> print a * 3
> 9.6

Not so. Decimal suffers from the exact same problem, just with different
numbers:

>>> import decimal
>>> x = decimal.Decimal('1')/decimal.Decimal('3')
>>> 3*x == 1
False

Some numbers can't be represented exactly in base 2, and some numbers
can't be represented exactly in base 10.


--
Steven

Steven D'Aprano

unread,
Jun 26, 2009, 6:04:04 AM6/26/09
to
On Thu, 25 Jun 2009 12:31:05 -0700, Mark Dickinson wrote:

>> We all know that IEEE floating point is a horribly inaccurate
>> representation [...]
>
> That's a bit extreme! Care to elaborate?

Well, 0.1 requires an infinite number of binary places, and IEEE floats
only have a maximum of 53 or so, so that implies that floats are
infinitely inaccurate...

*wink*


--
Steven

pdpi

unread,
Jun 26, 2009, 10:09:25 AM6/26/09
to
On Jun 26, 11:01 am, Steven D'Aprano <st...@REMOVE-THIS-

But since 10 = 2 * 5, all numbers that can be finitely represented in
binary can be represented finitely in decimal as well, with the exact
same number of places for the fractional part (and no more digits
than the binary representation in the integer part)

Scott David Daniels

unread,
Jun 26, 2009, 11:07:24 AM6/26/09
to
pdpi wrote:
> ... But since 10 = 2 * 5, all numbers that can be finitely represented in

> binary can be represented finitely in decimal as well, with the exact
> same number of places for the fractional part (and no more digits
> than the binary representation in the integer part)

OK, so base 30 is the obvious choice, digits and letters, and 1/N works
for n in range(1, 7) + range(8, 11). G�del numbers, anyone? :-)

--Scott David Daniels
Scott....@Acm.Org

Andre Engels

unread,
Jun 26, 2009, 11:17:03 AM6/26/09
to Scott David Daniels, pytho...@python.org
On Fri, Jun 26, 2009 at 5:07 PM, Scott David
Daniels<Scott....@acm.org> wrote:
> pdpi wrote:
>>
>> ... But since 10 = 2 * 5, all numbers that can be finitely represented in
>> binary can be represented finitely in decimal as well, with the exact
>> same number of  places for the fractional part (and no more digits
>> than the binary representation in the integer part)
>
> OK, so base 30 is the obvious choice, digits and letters, and 1/N works
> for n in range(1, 7) + range(8, 11).  Gödel numbers, anyone? :-)

To get even more working, use real rational numbers: p/q represented
by the pair of numbers (p,q) with p,q natural numbers. Then 1/N works
for every N, and upto any desired precision.


--
André Engels, andre...@gmail.com

Robert Kern

unread,
Jun 26, 2009, 3:44:29 PM6/26/09
to pytho...@python.org
On 2009-06-26 02:17, Ulrich Eckhardt wrote:
> Robert Kern wrote:
>> I wish people would stop representing decimal floating point arithmetic as
>> "more accurate" than binary floating point arithmetic.
>
> Those that failed, learned. You only see those that haven't learnt yet.
>
> Dialog between two teachers:
> T1: Oh those pupils, I told them hundred times! when will they learn?
> T2: They did, but there's always new pupils.

Unfortunately, I keep seeing people who claim to be old hands at floating point
making these unlearned remarks. I have no issue with neophytes like the OP
expecting different results and asking questions. It is those who answer them
with an air of authority that need to take a greater responsibility for knowing
what they are talking about. I lament the teachers, not the pupils.

Michael Torrie

unread,
Jun 26, 2009, 6:27:18 PM6/26/09
to pytho...@python.org
Robert Kern wrote:
> In the former case, you can claim that decimal floating point is more accurate
> *for those problems*. But as soon as you have a division operation, decimal
> floating point has the same accuracy problems as binary floating point.

True. Poor choice of words on my part. No matter what representation
one chooses for numbers, we can remember that digits != precision.
That's why significant digits were drilled into our heads in physics!
That's the reason IEEE actually works out for most things that we need
floating point for.

Reply all
Reply to author
Forward
0 new messages