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 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.)


Previous Comments:
------------------------------------------------------------------------
[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;

    }

------------------------------------------------------------------------
[2011-04-06 19:39:39] der...@php.net

Floating point values have a limited precision. Hence a value might 
not have the same string representation after any processing. That also
includes writing a floating point value in your script and directly 
printing it without any mathematical operations.

If you would like to know more about "floats" and what IEEE
754 is, read this:
http://www.floating-point-gui.de/

Thank you for your interest in PHP.

.

------------------------------------------------------------------------
[2011-04-06 19:22:45] for-bugs at hnw dot jp

Description:
------------
When round() is called with 1 argument which value is between 1e15 and
2^53, round() returns non-rounded value even if the value has fractional
part.



For instance, though 1e15 is exact number as IEEE 754 double precision,
round(1e15+0.1) returns 1e15+0.1. I think 1e15 is better result.

Test script:
---------------
<?php

'ini_set("precision",18);

var_dump(round(1000000000000000.1));

Expected result:
----------------
float(1000000000000000)

Actual result:
--------------
float(1000000000000000.12)


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



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

Reply via email to