Google

Jun 28, 2014

Working with Java BigDecimal class for monetary values

When you are working with monetary values in Java, you must use a BigDecimal data type. Many developers often have the following questions.

Q1. How to compare BigDecimal numerically?
This means 5.120 should be equal to 5.1200000. The default equals( ) implementation in BigDecimal class returns true only if two objects are numerically equivalent AND have the same scale(i.e. 5.120  is not equals( ) to 5.1200000).

Q2. How to check if an amount is zero, positive, or negative?
Q3. How to extract the decimal portion of the amount?
Q4. How to determine if it is an integer value?

Here is a utility class that answers the above questions


package com.writtentest10;

import java.math.BigDecimal;

public class BigDecimalUtils {

 private BigDecimalUtils() {

 }

 /**
  * The 'equals'  method in BigDecimal class returns true 
  * only if the two objects are numerically equivalent AND
  * have the same scale so (4.130 != 4.130000000)
  * 
  * This method returns true if the two values are numerically equivalent
  * 
  */
 public static boolean equals(BigDecimal value1, BigDecimal value2) {
  return (value1.compareTo(value2) == 0);
 }

 public static boolean isZero(BigDecimal value) {
  return (value.signum() == 0);
 }

 public static boolean isNonZero(BigDecimal value) {
  return (value.signum() != 0);
 }

 public static boolean isPositive(BigDecimal value) {
  return (value.signum() == 1);
 }

 public static boolean isNegative(BigDecimal value) {
  return (value.signum() == -1);
 }

 public static BigDecimal getExponent(BigDecimal value) {
  return BigDecimal.valueOf(value.longValue());
 }

 public static BigDecimal getMantissa(BigDecimal value) {
  if (isZero(value)) {
   return value;
  }

  BigDecimal result = value.abs();
  BigDecimal exponent = getExponent(result);

  if (isZero(exponent)) {
   return result;
  }

  return result.subtract(exponent);
 }

 public static boolean isInteger(BigDecimal value) {
  return isZero(value) ? false : isZero(getMantissa(value));
 }

}



The JUnit test class

package com.writtentest10;

import java.math.BigDecimal;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class BigDecimalUtilsTest {

 private boolean setUpIsDone = false;

 private BigDecimal positiveValue1;
 private BigDecimal positiveValue2;
 private BigDecimal negativeValue;

 @Before
 public void init() {

  if (setUpIsDone) {
   return;
  }

  positiveValue1 = BigDecimal.valueOf(25.12);
  positiveValue2 = BigDecimal.valueOf(25.1200);
  negativeValue = BigDecimal.valueOf(-25.12);

  setUpIsDone = true;
 }

 @Test
 public void testEqual() {
  Assert.assertTrue(BigDecimalUtils.equals(positiveValue1, positiveValue2));
  Assert.assertFalse(BigDecimalUtils.equals(positiveValue1, negativeValue));
 }
 
 
 @Test
 public void testPositiveNegativeAndZero() {
  Assert.assertTrue(BigDecimalUtils.isPositive(positiveValue1));
  Assert.assertTrue(BigDecimalUtils.isNegative(negativeValue));
  Assert.assertTrue(BigDecimalUtils.isZero(BigDecimal.ZERO));
  
  Assert.assertFalse(BigDecimalUtils.isPositive(negativeValue));
  Assert.assertFalse(BigDecimalUtils.isNegative(positiveValue1));
  Assert.assertFalse(BigDecimalUtils.isZero(positiveValue1));
 }
 
 
 
 @Test
 public void testGetMantissa() {
  Assert.assertEquals(BigDecimal.valueOf(0.12),BigDecimalUtils.getMantissa(positiveValue1));
  Assert.assertEquals(BigDecimal.valueOf(0.12),BigDecimalUtils.getMantissa(positiveValue2));
  Assert.assertEquals(BigDecimal.valueOf(0.12),BigDecimalUtils.getMantissa(negativeValue));
 }
 
 
 @Test
 public void testIsInteger() {
  Assert.assertFalse(BigDecimalUtils.isInteger(positiveValue1));
  Assert.assertFalse(BigDecimalUtils.isInteger(negativeValue));
  Assert.assertTrue(BigDecimalUtils.isInteger(BigDecimal.ONE));
  Assert.assertFalse(BigDecimalUtils.isInteger(BigDecimal.ZERO));
  Assert.assertTrue(BigDecimalUtils.isInteger(BigDecimal.valueOf(12.00)));
 }
}


Here is a real life example of using BigDecimal for monetary calculation with design patterns.

Labels: ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home