Jivago
Jivago

Reputation: 826

Currency rounding inconsistencies in AS3

while building an accounting system, I came across a major problem. Let's say I do an invoice and then, I have to apply a credit with the same amount as a negative value, I sometimes have a rounding problem of 1¢..

My problem is regarding negative values only!

Let's have a look at this script that is testing a specific positive and negative value. For debugging purpose, I also send the parameter expectedResult ;

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="creationCompleteHandler()">

    <fx:Script>
        <![CDATA[
            import mx.formatters.CurrencyFormatter;
            import mx.formatters.NumberBaseRoundType;

            private function roundDecimal(num:Number, expectedResult:Number):void
            {
                var rnd:CurrencyFormatter = new CurrencyFormatter();
                rnd.precision = 2;
                rnd.useThousandsSeparator = false;
                rnd.currencySymbol = '';

                if (num >= 0)
                    rnd.rounding = NumberBaseRoundType.NEAREST;
                else
                    rnd.rounding = NumberBaseRoundType.DOWN; // The problem is here, ALWAYS!

                var result:Number = Number(rnd.format(num));

                if (result != expectedResult)
                    trace("Error : " + result + " (Expecting " + expectedResult + ")");
                else
                    trace("OK : " + result);
            }

            protected function creationCompleteHandler():void
            {
                var num:Number;
                var expectedResult:Number;

                // Test number 1
                num = 5.653;
                expectedResult = 5.65;
                roundDecimal(num, expectedResult);
                roundDecimal(-(num), -(expectedResult));

                trace("------------");

                // Test number 2
                num = 5.655;
                expectedResult = 5.66;
                roundDecimal(num, expectedResult);
                roundDecimal(-(num), -(expectedResult));

                trace("------------");

                // Test number 3
                num = 5.657;
                expectedResult = 5.66;
                roundDecimal(num, expectedResult);
                roundDecimal(-(num), -(expectedResult));

            }
        ]]>
    </fx:Script>

</s:WindowedApplication>

Of course I tried to modify the rounding type for negative values, without success..

Have a look at the different rounding types and their results :

//////////// Test 1 ////////////
if (num >= 0)
    rnd.rounding = NumberBaseRoundType.NEAREST;
else
    rnd.rounding = NumberBaseRoundType.DOWN; // The problem is here, ALWAYS!

OK : 5.65
Error : -5.66 (Expecting -5.65)
------------
OK : 5.66
OK : -5.66
------------
OK : 5.66
OK : -5.66

//////////// Test 2 ////////////
if (num >= 0)
    rnd.rounding = NumberBaseRoundType.NEAREST;
else
    rnd.rounding = NumberBaseRoundType.UP;

OK : 5.65
OK : -5.65
------------
OK : 5.66
Error : -5.65 (Expecting -5.66)
------------
OK : 5.66
Error : -5.65 (Expecting -5.66)

//////////// Test 3 ////////////
if (num >= 0)
    rnd.rounding = NumberBaseRoundType.NEAREST;
else
    rnd.rounding = NumberBaseRoundType.NEAREST; // The problem is here, ALWAYS!

OK : 5.65
OK : -5.65
------------
OK : 5.66
Error : -5.65 (Expecting -5.66)
------------
OK : 5.66
OK : -5.66

I'm really stuck here and would appreciate some help.. Thanks a lot!!

Upvotes: 1

Views: 396

Answers (2)

Gone3d
Gone3d

Reputation: 1189

Check to see if it's positive or negative and assign a sign to a var (1 or -1), take the absolute value ( Math.abs(value)) and round that. Then multiply it by the sign to get the result.

That way you always get the same result and the whether it is positive or negative doesn't matter.

Upvotes: 1

Vesper
Vesper

Reputation: 18747

You are actually expecting the rounding to provide opposite results for negative values than you want for positive. A simple measure would be rounding DOWN for positive values and UP for negative. (Or up for positive and down for negative, valid too). The trick is, NEAREST always rounds up if the value is right in the middle of two possible rounding outcomes, and you want it to round down negative numbers only.

Upvotes: 0

Related Questions