Hi,

>   Modified files:              (Branch: PHP_5_3)
>     /php-src/ext/standard     math.c 
>   Log:
>   Fixed bug #42294 (Unified solution for round() based on C99 round)
>   [DOC] New implementation of round() to work-around inconsistencies for win32
>   and 64 bit platforms.
>   
>   This solution is very roughly based on BSD's implmentation of round(), which
>   itself is an implementation of C99 standard. We take the absolute value of 
> number
>   we want to round time the 10 to the power of the number of decimal spaces 
> we are 
>   rounding to. The resulting value is rounded up and the pre-rounded value is 
>   subtracted from it. If the difference is greater then 0.5000000001 we round 
> up,
>   otherwise we round down.

Apparently, nobody reads internals anymore. :-(

I made my initial comment on the bug report over a year ago. Since then
I've dug quite a bit into floating point arithmetics and the actual
problems behind round(). This lead to:

http://wiki.php.net/rfc/rounding

Which I posted quite a while ago and nearly nobody was interested:

http://news.php.net/php.internals/40070

[Now please don't simply apply the patch there, I've done some
additional research since.]

The solution I proposed over a year ago is actually wrong and it does
not solve all the problems of round()'s g, see my RFC for that.

The general problems with round are actually:

1) Internal FPU precision on x86.
2) Specification problem (which rounding mode should actually be used?)
3) Dividing/multiplying by >= 10^23 is not exact.
4) round (1.255, 2) should give 1.26 but gives 1.25. The FUZZ stuff
   tries to resolve this issue (but not the other three) but I've
   come to the conclusion that the FUZZ is actually the wrong solution
   for the problem.

Since I didn't get any reaction on the RFC on internals, I pinged Lukas
and Johannes (as they are RMs for PHP 5.3) in private in order to ask
whether it was possible to include my proposal in 5.3 (I don't have ZE2
Karma and my patch also needs to change zend_strtod).

Lukas and Johannes were concerned about the interopability of my
solution of problem (1). So I did some tests on different platforms and
operating systems and Lukas and Johannes asked around for other people
to do tests, too. I've summarized results of these tests and proposed
solution for correct cross-platform floating point arithmetics here:

http://www.christian-seiler.de/projekte/fpmath/

I've mailed patches for PHP 5.3 and HEAD to Johannes and Lukas for
ZendEngine2 that only address the above issue (1) and do the following:

1) Define some macros for math-related functions that will ensure the
function itself always uses double precision. Add configure checks for
these macros.

2) Modified zend_strtod and the add/sub/div/mul functions in
zend_operators.c to make use of those macros. This ensures that PHP will
always use double precision for calculations and math is thus portable.

3) Added a test that determines if the calculations precision is
actually correct.

The patches for 5.3 and HEAD are found here:

http://www.christian-seiler.de/temp/php/2008-10-28-fpu/php-float-precision-5.3.patch
http://www.christian-seiler.de/temp/php/2008-10-28-fpu/php-float-precision-6.patch

My next step (as discussed with Johannes and Lukas) would have been to
apply the Non-ZE2-part of my patch to ext/standard/math.c in 5.3 and
HEAD (I don't have separate patches for that yet but they are quite
trivial to adapt to the new macros).

Now the question is: Where do we go from here? Your commit does not
solve all the problems of PHP's round but is at least better than the
previous implementation since at least the platform-dependency on
whether or not to use the FUZZ is removed. The other problems, however,
remain.

Christian

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to