I need to round prices for my client in a non-common way :
120.28 => 120.2
130.23 => 130.2
150.64 => 150.6
The rule is to always keep the nearest lowest 1 precision.
I try to use the round()
method but all my tries are useless since this method handle half which i have to ignore.
ceil()
and floor()
will not work out of the box.
Is a combination of those 3 methods would work ?
2
Answers
phpHow about
0.1 * intval(10 * $price)
?What it does is multiply the price by 10, so 120.28 becomes 1202.8. Then it takes integer part using intval(), which is 1202, and then divides it by ten giving 120.2.
See: https://3v4l.org/3qMhd
I think the problem indicated by jspit is relevant, we could compensate for prices that are just a hair under their expected value. Something like this:
It works, see https://3v4l.org/5YCEu.
The value 1E-6 is chosen with care, not too much or too little.
floating points in PHP have roughly 16 digits of precision and money is usually not more than a few billion. Billions use 9 or 10 digits, subtract that from the 16 we have and you get the 6.
Also, 6 digits should be ample. If an amount is 10.599999 it will still be converted to 10.5. Only when it is even closer, say 10.5999999 will it become 10.6.
You may want to put this point somewhere else. You could decide that 10.555 should be 10.6. Then you choose a value of 0.45. See; https://3v4l.org/YWVI0. The point is that you can exactly choose where you want this point to be, no more surprises.
I think the solution
0.1 * intval(10 * $price)
causes problems when prices are the result of calculations.The following solution avoids this error by rounding to 2 decimal places and truncating using a string function.
Demo: https://3v4l.org/hFjDL