Re: Formatting Decimals
| From: | Adam Richardson | Date: | Tue, 12 Jan 2010 03:39:21 +0000 |
| Subject: | Re: Formatting Decimals | ||
| References: | 1 2 3 4 5 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-301008@lists.php.net to get a copy of this message | ||
On Mon, Jan 11, 2010 at 7:45 PM, Mattias Thorslund <mattias@thorslund.us>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