Banker's Rounding for PHP
Via Slashdot I found this detailed article regarding various rounding methods. There are a lot more ways to think about it besides just rounding up to the next highest digit on the fives.
The article reminded me of a problem I worked on last fall. PHP’s standard rounding function round always rounds the fives up. This was causing an upward creep in my calculations for hours worked in time clock data. I needed a way to minimize that creep. I settled on a different method of rounding known as “banker’s rounding.” This method alternates the rounding of fives based on the even-/odd-ness of the preceding digit. So for example, a 3.5 rounds up to 4 and a 4.5 rounds down to 4.
I have created a PHP function to do this, and the source code is here: GPL version; BSD version. You give the bround function two parameters: first the value to round, and second how many decimal places to keep. So bround(3.55,0) produces 4 and bround(3.55,1) produces 3.6.
I hope it’s helpful to someone and please don’t hesitate to report bugs or a faster way to do this. (Normally I’m not a fan of using the Ternary Operator but in this case it keeps the function compact and is fairly straightforward.)
Update 2007-04-23: Someone going by the name of “Hitlers Pet Gerbil” replied to my method stating it was “slightly incorrect.” I posted a reply to the comment on the PHP site, but for some reason it was deleted. Today I stumbled upon a copy of my response, which was written on October 6 of last year:
In reply to Mr. Pet Gerbil, I think you’re wrong when you state “Your calculations are slightly incorrect.” My calculations do take into account when the thousandth’s digit is a 5. I ran your function and mine side-by-side and got the same results.
However, I found your string-based method to be interesting and it runs faster than my code in testing. It would need some adjustment to allow the user to specify the number of decimal places. My function does not assume the user wants to round to two decimal places, though that likely is what the user will want.
Update 2007-10-01: Added BSD-style licensed version (see above).