On Mon, Jan 11, 2010 at 7:45 PM, Mattias Thorslund <mattias@xxxxxxxxxxxx>wrote: > tedd wrote: > >> At 2:55 PM -0500 1/11/10, Rick Dwyer wrote: >> >>> I have been asked to further modify the value to the nearest half cent. >>> >>> So if the 3rd decimal spot ends in 1 or 2, it gets rounded down to 0 >>> If it ends in 3, 4, 5, 6 it gets rounded to 5. And if it 7, 8 or 9 it >>> gets rounded up to full cents. >>> >>> Can this be done fairly easily? Not knowing PHP well, I am not aware of >>> the logic to configure this accordingly. >>> >>> Thanks, >>> --Rick >>> >> >> >> --Rick: >> >> The above described rounding algorithm introduces more bias than simply >> using PHP's round() function, which always rounds down. IMO, modifying >> rounding is not worth the effort. >> >> The "best" rounding algorithm is to look at the last digit and do this: >> >> 0 -- no rounding needed. >> 1-4 round down. >> 6-9 round up. >> >> In the case of 5, then look to the number that precedes it -- if it is >> even, then round up and if it is odd, then round down -- or vise versa, it >> doesn't make any difference as long as you are consistent. >> >> Here are some examples: >> >> 122.4 <-- round down (122) >> 122.6 <-- round up (123) >> 122.5 <-- round up (123) >> >> 123.4 <-- round down (123) >> 123.6 <-- round up (124) >> 123.5 <-- round down (123) >> >> There are people who claim that there's no difference, or are at odds with >> this method, but they simply have not investigated the problem sufficiently >> to see the bias that rounding up/down causes. However, that difference is >> very insignificant and can only be seen after tens of thousands iterations. >> PHP's rounding function is quite sufficient. >> >> Cheers, >> >> tedd >> >> > However that's not what Rick is asking for. He needs a function that rounds > to the half penny with a bias to rounding up (greedy bosses): > > > Actual Rounded Diff > .011 .010 -.001 > .012 .010 -.002 > .013 .015 +.002 > .014 .015 +.001 > .015 .015 .000 > .016 .015 -.001 > .017 .020 +.003 > .018 .020 +.002 > .019 .020 +.001 > .020 .020 .000 > Bias +.005 > > This could easily be implemented by getting the 3rd decimal and using it in > a switch() statement. > > An unbiased system could look like: > > Actual Rounded Diff > .011 .010 -.001 > .012 .010 -.002 > .013 .015 +.002 > .014 .015 +.001 > .015 .015 .000 > .016 .015 -.001 > .017 .020 -.002 > .018 .020 +.002 > .019 .020 +.001 > .020 .020 .000 > Bias .000 > > The only difference is the case where the third decimal is 7. > > Cheers, > > Mattias > > > -- > PHP General Mailing List (http://www.php.net/) > To unsubscribe, visit: http://www.php.net/unsub.php > > Here you go, Rick. Just send the check in the mail ;) function round_to_half_cent($amount) { if (!is_numeric($amount)) throw new Exception('The amount received by the "round_to_half_cent" function was not numeric'); $parts = explode('.', str_replace(',', '', (string)$amount)); if (count($parts) >= 3) throw new Exception('The amount received by the "round_to_half_cent" function had too many decimals.'); if (count($parts) == 1) { return $amount; } $digit = substr($parts[1], 2, 1); if ($digit == 0 || $digit == 1 || $digit == 2) { $digit = 0; } elseif ($digit == 3 || $digit == 4 || $digit == 5 || $digit == 6) { $digit = .005; } elseif ($digit == 7 || $digit == 8 || $digit == 9) { $digit = .01; } else { throw new Exception('OK, perhaps we are talking about different types of numbers :( Check the input to the "round_to_half_cent" function.'); } return (double)($parts[0].'.'.substr($parts[1], 0, 2)) + $digit; } echo "5.002 = ".round_to_half_cent(5.002); echo "<br />70,000.126 = ".round_to_half_cent("70000.126"); echo "<br />55.897 = ".round_to_half_cent(55.897); // should cause exception echo "<br />One hundred = ".round_to_half_cent("One hundred"); -- Nephtali: PHP web framework that functions beautifully http://nephtaliproject.com