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

Mark Dickinson dickinsm at gmail.com
Thu Jun 25 21:31:05 CEST 2009

```On Jun 25, 7:41 pm, Michael Torrie <torr... at 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

```