I was relying on sprintf(\'%0.1f\', 2.25) === \'2.3\'
but it turns out it comes in at 2.2
!
In fact it seems random:
php >
You should be using round
http://php.net/manual/en/function.round.php
round(2.25, 2) === floatval('2.3')
As an explanation of why round
can offer better results than a function not specifically designed for rounding, we need to consider the limits of the double precision floating point representation. Doubles can represent between 15 and 17 decimal significand digits. From the Wikipedia article on double precision:
If a decimal string with at most 15 significant digits is converted to IEEE 754 double precision representation and then converted back to a string with the same number of significant digits, then the final string should match the original. If an IEEE 754 double precision is converted to a decimal string with at least 17 significant digits and then converted back to double, then the final number must match the original
The implementation of round
can and should make use of this to "do the right thing" in most cases.
Example 1:
<?=number_format(2.05,14); //give me 15 significant digits. Guaranteed to produce the orginal number
outputs:
2.05000000000000
Example 2:
<?=number_format(2.05,16); //give me 17 significant digits. Not guaranteed to produce the orginal number
outputs:
2.0499999999999998
This is just a demonstration the IEEE 754 behavior.
I am going to guess (because I haven't read its implementation) that sprintf
doesn't really try to do anything particularly intelligent with regards to rounding, whereas round
probably tries to round "correctly" (per IEEE 754) with respect to the number of significant digits you asked for.
To summarise what has been said in comments in an answer:
Because printf
is not a rounding function, but a low-level function to give a string representation of a number. In this case the number internally is not the same as the number set, e.g. it might be 2.249999991231231123
because of the limitations of the floating point internal representation.
So printf
is rounding a different number to that which you entered/calculated, which is correctly 2.2
in this example.
Therefore as the other answer (and my original question) points out, a better solution is to use round()
(and possibly sprintf
upon the result).