[php-maint] Bug#603292: Bug#603292: libapache2-mod-php5: PHP5 does not round correctly
Ondřej Surý
ondrej at debian.org
Mon Nov 15 06:52:27 UTC 2010
Bob,
thanks for comprehensive explanation. Would you be willing to put this
information to f.e. http://wiki.debian.org/PHP/Rounding and link it
from http://wiki.debian.org/PHP (or just in
http://wiki.debian.org/PHP/Rounding), so it doesn't disappear when
this bug is archived?
Ondrej
On Mon, Nov 15, 2010 at 06:13, Bob Proulx <bob at proulx.com> wrote:
> Markus Knaup wrote:
>> PHP5 does not round correctly.
>> echo round(1.025, 2) . "<br />";
>
> Note that this is the same behavior as C's printf. Also the shell's
> printf which makes that behavior available to the command line
> produces the same behavior.
>
> $ printf "%.2f\n" 1.025
> 1.02
>
> But it just didn't seem satisfying to say that it isn't a bug in PHP
> because that is just the way floating point computer engines work.
> But that is basically the reason. That is the way floating point
> works on machines. But being unsatisfying I wanted to add some more
> information about the problem.
>
> For the underlying reasons you need to look at the encoded binary
> values. A typical issue is that exact terminating decimal fractions
> may not have an exact binary representation. Therefore converting
> from decimal to binary creates an error.
>
> 1.020 => 1.00000101000111101011100001010001111010111000010100011110101110...
> 1.025 => 1.00000110011001100110011001100110011001100110011001100110011001...
> 1.030 => 1.00000111101011100001010001111010111000010100011110101110000101...
>
> Since there are an infinite number of digits needed this can't be used
> without reducing the number of digits in the calculation. That means
> that floating point operations routinely introduce errors into
> calculations. As to the exact details of rounding fractional digits I
> have always avoided needing to know that information. I have avoided
> it because when I needed an exact value I knew about the problems and
> instead used scaled integers. And so I can't give a better
> explanation now. Only a recommendation to avoid it too.
>
> Remember that floating point is only an approximation of reality. For
> more exact answers you may want to use binary coded decimal or scaled
> integers. This example is a good one to show why floating point isn't
> used for monetary transactions. My personal history is with CAD/EDA
> software and in that problem domain most software uses scaled integers
> to avoid these types of errors.
>
> There have been recent changes in the way PHP handles rounding.
> The upstream PHP documentation lists:
>
> 5.3.0 The mode parameter was introduced.
>
> 5.2.7 The inner workings of round() was changed to conform to the
> C99 standard.
>
> In 5.3.0 and later (Sid or Squeeze) the mode parameter gives you some
> control over rounding.
>
> $ php -r 'echo round(1.025,2,PHP_ROUND_HALF_UP) . "\n";'
> 1.03
>
> Also the default rounding mode has changed too.
>
> $ php -r 'echo round(1.025,2) . "\n";'
> 1.03
>
> Hope that helps,
> Bob
>
> P.S. Here are some useful references.
>
> http://en.wikipedia.org/wiki/Double_precision_floating-point_format
>
> http://en.wikipedia.org/wiki/Floating_point#Rounding_modes
>
> http://en.wikipedia.org/wiki/Binary_numeral_system#Decimal
>
> http://en.wikipedia.org/wiki/Binary_numeral_system#Representing_real_numbers
>
> http://cs.furman.edu/digitaldomain/more/ch6/dec_frac_to_bin.htm
>
> http://www.exploringbinary.com/binary-converter/
>
>
>
> _______________________________________________
> pkg-php-maint mailing list
> pkg-php-maint at lists.alioth.debian.org
> http://lists.alioth.debian.org/mailman/listinfo/pkg-php-maint
>
--
Ondřej Surý <ondrej at sury.org>
http://blog.rfc1925.org/
More information about the pkg-php-maint
mailing list