Edit report at http://bugs.php.net/bug.php?id=54479&edit=1

 ID:                 54479
 Comment by:         exploringbinary at gmail dot com
 Reported by:        for-bugs at hnw dot jp
 Summary:            round(1e15+0.1) returns 1e15+0.1 instead of 1e15
 Status:             Bogus
 Type:               Bug
 Package:            Math related
 Operating System:   any
 PHP Version:        5.3.6
 Block user comment: N
 Private report:     N

 New Comment:

I said round(1000000000000000.125,3) returns 1.0E+15, but that's not
true: ECHO returns that. round() seems to work as I expect for this
example if I show it with printf:



<?php echo round(1000000000000000.125,3); // Prints 1.0E+15 ?>



<?php printf("%.3f",round(1000000000000000.125,3)); // Prints
1000000000000000.125 ?>





(Interestingly, printf("%.3f",round(1000000000000000.125,0)) prints
1000000000000000.125)


Previous Comments:
------------------------------------------------------------------------
[2011-04-17 03:02:52] cataphr...@php.net

PHP simplifies the round implementation by giving up more or less around
when the accuracy falls below one. This is indeed a bit lazy even though
the units digit is not accurate; without checking the algorithm/history
maybe the purpose is to avoid the algorithm doesn't terminate due to
adding numbers >=1 having no effect in the result.



In any case, feel free to propose a patch.

------------------------------------------------------------------------
[2011-04-16 20:39:18] exploringbinary at gmail dot com

I would think since 1000000000000000.125 is exactly representable (53
bits), round(1000000000000000.125,3) would return 1000000000000000.125;
but on PHP 5.3.5, it returns 1.0E+15. Compare this to
printf("%.3f",1000000000000000.125), which prints
1000000000000000.125.(See http://bugs.php.net/bug.php?id=53918 for
discussion on printing exactly representable values.)

------------------------------------------------------------------------
[2011-04-10 21:57:47] uncorrelated at yahoo dot co dot jp

I'm suprized that floating point numbers of PHP doesn't support for IEEE
754. I'd like to confirm wheather PHP 5.3 supports for IEEE 754 or not.



IEEE 754 ensures that 1000000000000000 differs from 1000000000000000.125
(see appendix). Then, IEEE 754 requires round(1000000000000000.125)
returns 1000000000000000. In fact, the function of PHP 5.2.17 returns
1000000000000000.



In spite of that, the function of PHP 5.3.6 returns
1000000000000000.125. It seems to be strange. If it is NOT a bug, PHP
5.3 doesn't support IEEE 754.

Mr hnw may think that PHP should support for IEEE 754 as long as the
system allows it, and the cutoff (precious) value shouldn't affect any
operation but printing. 



Appendix:



(Decimal)1000000000000000.125 is represented as the followings:

Bits of Sign: 0 

Bits of Exponent: 10000110000 

Bits of Significand:
1100011010111111010100100110001101000000000000000001



(Decimal)1000000000000000 is represented as the followings:

Bits of Sign: 0 

Bits of Exponent: 10000110000

Bits of Significand:
1100011010111111010100100110001101000000000000000000



The significand of 1000000000000000.125 isn't same as that of
1000000000000000 (See the right edges of them).

------------------------------------------------------------------------
[2011-04-07 14:19:06] cataphr...@php.net

If anything, the cutoff value is too high:



The accuracy (effective number of digits to the right of the decimal
point) of a double is given by 15.9546-log10(|x|) and:



In[22]:= Solve[$MachinePrecision-Log[10, Abs[x]]==1.,x]

                         14

Out[22]= {{x -> 9.0072 10  }}

------------------------------------------------------------------------
[2011-04-07 01:52:10] for-bugs at hnw dot jp

My test script seems to be wrong. How about next one?





<?php

ini_set("precision",19);

var_dump(1000000000000000.125);

// float(1000000000000000.125)

var_dump(round(1000000000000000.125));

// PHP 5.3.6 returns float(1000000000000000.125)

// PHP 5.2.17 returns float(1000000000000000)





IEEE 754 double precision have 53 bit fractions, so 1000000000000000 and
1000000000000000.125 is exact number.





This behavior is caused by ext/standard/math.c:160-163



    /* This value is beyond our precision, so rounding it is pointless
*/

    if (fabs(tmp_value) >= 1e15) {

      return value;

    }

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    http://bugs.php.net/bug.php?id=54479


-- 
Edit this bug report at http://bugs.php.net/bug.php?id=54479&edit=1

Reply via email to