Wednesday, March 17, 2010

Australian Money rounding in Java and JavaScript

Money rounding is a little bit difficult in Australia, since the smallest coin is 5 cent and HALF_EVEN is not enough. It requires rounding to nearest 5 cents for Australian businesses. For example, $5.96 rounds to $5.95.
$5.98 goes to $6, kinds of ONE_FOURTH_EVEN.

To implement Australian dollar rounding, I use a kind of stupid solution, introducing an rounding map.
roundingMap.put(1, new BigDecimal("-0.01"));
  roundingMap.put(2, new BigDecimal("-0.02"));
  roundingMap.put(3, new BigDecimal("0.02"));
  roundingMap.put(4, new BigDecimal("0.01"));
  roundingMap.put(6, new BigDecimal("-0.01"));
  roundingMap.put(7, new BigDecimal("-0.02"));
  roundingMap.put(8, new BigDecimal("0.02"));
  roundingMap.put(9, new BigDecimal("0.01"));
This map contains number 1,2,3,4,6,7,8,9 which need to be rounded. To round a amount, simply get the last digital and get the rounding value.

for example, the last digital for $5.96 is 6. The rounding value for key 6 is -0.01. the final result is $5.96-0.01=5.95.

This implementation is not very smart but it's the best I can figure out.

Here is the full solution.
In JAVA:
The Rounding Class:
import java.math.BigDecimal;
import java.util.HashMap;

/**
 * Rounding to nearest 5 cents for Australian businesses
 * 
 * @author Ke CAI
 */
public class MoneyRounding {
 static HashMap roundingMap = new HashMap();
 static {
  roundingMap.put(1, new BigDecimal("-0.01"));
  roundingMap.put(2, new BigDecimal("-0.02"));
  roundingMap.put(3, new BigDecimal("0.02"));
  roundingMap.put(4, new BigDecimal("0.01"));
  roundingMap.put(6, new BigDecimal("-0.01"));
  roundingMap.put(7, new BigDecimal("-0.02"));
  roundingMap.put(8, new BigDecimal("0.02"));
  roundingMap.put(9, new BigDecimal("0.01"));

 }

 public static BigDecimal getRounding(BigDecimal bd) {
  int decimalDigit = bd.movePointRight(2).intValue() % 10;
  BigDecimal mappedVal = (BigDecimal) roundingMap.get(decimalDigit);
  if (mappedVal == null)
   return BigDecimal.ZERO;
  return mappedVal;
 }

}


Unit test and how to use Rounding Test:
import static org.junit.Assert.assertEquals;

import java.math.BigDecimal;

import org.junit.Test;

public class RoundingTest {

 @Test
 public void testRounding() {
  
  BigDecimal amout = new BigDecimal("15.58");

  BigDecimal rounding = MoneyRounding.getRounding(amout);
  assertEquals(rounding, new BigDecimal("0.02"));
  
  BigDecimal amout1 = new BigDecimal("15.56");

  BigDecimal rounding1 = MoneyRounding.getRounding(amout1);
  assertEquals(rounding1, new BigDecimal("-0.01"));
  
 }

}

The following is how to implement it in JavaScript:
var Rounding = function( ){
 function getRounding(amount){
 var roundingMap={1:-0.01,2:-0.02,3:0.02,4:0.01,6:-0.01,7:-0.02,8:0.02,9:0.01};
 var  decimalDigit =amount*100%10;
 return roundingMap[decimalDigit];
}

//test
var amount=15.59;
alert(getRounding(amount));

0 comments: