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