Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Make cents with BigDecimal

Write Java programs to calculate and format currency

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Page 2 of 3

BigDecimal operations

BigDecimal methods for adding and subtracting numbers are add() and subtract(), respectively. For example, to add 1,115.37 and 115.37, we could do the following:

BigDecimal balance = new BigDecimal("1115.37");
BigDecimal transaction = new BigDecimal("115.37");
BigDecimal newBalance = balance.add(transaction);  


The BigDecimal's newBalance object now holds the value of 1,230.74. Similarly, to subtract 115.37 from 1,115.37, we could use this code:

BigDecimal balance = new BigDecimal("1115.37");
BigDecimal transaction = new BigDecimal("115.37");
BigDecimal newBalance2 = balance.subtract(transaction);      


The BigDecimal's newBalance2 object now holds the value of 1,000.00. (Naturally, if we are talking about checkbook balances in real life, the subtract() method will be used much more often than the add() method, and the total amount subtracted from the checkbook balance will exceed the total amount added, or so it often seems.) You can accomplish multiplying and dividing with BigDecimal's multiply() and divide() methods. Multiplying is demonstrated in the following program:

import java.math.*;
import java.text.*;
import java.util.*;
public class Multiply {
   public static void main(String[] args) {
      BigDecimal d = new BigDecimal("1115.32");
      BigDecimal taxRate = new BigDecimal("0.0049");
      BigDecimal d2 = d.multiply(taxRate);
      System.out.println("Unformatted: " + d2.toString()); 
      NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US); 
      double money = d2.doubleValue();
      String s = n.format(money);
      System.out.println("Formatted:  " + s);
   }
}


The output for the above code is shown below:

Unformatted:   5.465068
Formatted:      .46


Note the extra decimal places in the unformatted BigDecimal object as compared to the formatted output. In addition, formatting the value of the BigDecimal object causes the fraction -- greater than one half -- to be dropped. To manage the extra decimal places and the lack of rounding, we can use BigDecimal's setScale() method to set the number of decimal places. When using setScale(), we need to specify not only the number of decimal places, but how the number will be rounded, if rounding is necessary. The most common way of rounding -- round up fractions half or greater, and round down all other fractions -- can be specified with BigDecimal's constant ROUND_HALF_UP. Therefore, to set the number of decimal places to two and specify that fractions half and greater will be rounded up, we can write:

d2 = d2.setScale(2, BigDecimal.ROUND_HALF_UP);


Modifying the above program to add setScale(), we now have:

import java.math.*;
import java.text.*;
import java.util.*;
public class Multiply2 {
   public static void main(String[] args) {
      BigDecimal d = new BigDecimal("1115.32");
      BigDecimal taxRate = new BigDecimal("0.0049");
      BigDecimal d2 = d.multiply(taxRate);
      d2 = d2.setScale(2, BigDecimal.ROUND_HALF_UP);
      System.out.println("Unformatted: " + d2.toString()); 
      NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US); 
      double money = d2.doubleValue();
      String s = n.format(money);
      System.out.println("Formatted:  " + s);
   }
}


Now the output is:

Unformatted:   5.47
Formatted:      .47


Now the BigDecimal value is rounded to two digits, rounding the value up, and the formatted String correctly displays the rounded value. Other constants useful in rounding are ROUND_HALF_DOWN and ROUND_HALF_EVEN. The first, ROUND_HALF_DOWN, rounds fractions of half and under down, and all others up. The second, ROUND_HALF_EVEN, rounds half fractions to the even number (e.g., 2.5 rounds to 2, while 3.5 rounds to 4), and fractions greater or less than half to the closest integer. When dividing BigDecimal objects, we are required to specify how the result will be rounded. For this article, we will round halves up. The following program shows some sample division:

import java.math.*;
import java.text.*;
import java.util.*;
public class Divide {
   public static void main(String[] args) {
      BigDecimal d = new BigDecimal("1115.32");
      BigDecimal days = new BigDecimal("30");
      BigDecimal d2 = d.divide(days, 2, BigDecimal.ROUND_HALF_UP); 
      NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US); 
      double money = d2.doubleValue();
      String s = n.format(money);
      System.out.println(s);
   }
}


Output from the above program is:

7.18


Calculating interest

For this example, assume that a sum of ,500 will receive interest payments at an annual rate of 6.7 percent. Payments will be calculated quarterly, and we will calculate the first quarterly payment. To do so, we will use the formula I=PRT, where I is the amount of interest, P is the principal (9,500), R is the rate (6.7 percent annually), and T is the time (0.25 years). The program is:

import java.math.*;
import java.text.*;
import java.util.*;
public class Interest {
   public static void main(String[] args) {
      BigDecimal principal = new BigDecimal("9500.00");
      BigDecimal rate = new BigDecimal("0.067");
      BigDecimal time = new BigDecimal("0.25");
      BigDecimal temp = principal.multiply(rate);
      BigDecimal interest = temp.multiply(time);
      NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US); 
      double money = interest.doubleValue();
      String s = n.format(money);
      System.out.println("First quarter interest:  " + s);    }
} 


Output from the above program is:

First quarter interest: 59.12


Mutual fund transactions

In this example, an investor owns 754.495 shares in a mutual fund. The investor makes an additional 00.00 purchase of shares at 0.38 per share. We will use the following Java program to answer two questions: How many shares does the investor own after purchase, and what is the current market value of the account after the purchase? We will assume that the mutual fund keeps track of share numbers to three decimal places:

import java.math.*;
import java.text.*;
import java.util.*;
public class Mutual {
   public static void main(String[] args) {
      BigDecimal shares = new BigDecimal("754.495");
      BigDecimal purchaseAmount = new BigDecimal("200.00"); 
      BigDecimal pricePerShare = new BigDecimal("10.38");
      BigDecimal sharesPurchased = purchaseAmount.divide(pricePerShare, 3, BigDecimal.ROUND_HALF_UP);
      shares = shares.add(sharesPurchased);
      BigDecimal accountValue = shares.multiply(pricePerShare); 
      NumberFormat n = NumberFormat.getCurrencyInstance(Locale.US); 
      double dAccountValue = accountValue.doubleValue();
      String sAccountValue = n.format(dAccountValue);
      System.out.println("Number of shares = " + shares.toString()); 
      System.out.println("Account value = " + sAccountValue);   }
}


The above program outputs:

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comments (4)
Login
Forgot your account info?

Too many typosBy Anonymous on August 19, 2009, 11:35 amMost significant digit truncated in many places.

Reply | Read entire comment

Helpful - Small typoBy Anonymous on August 7, 2009, 5:56 pmHelpful article - I think "The investor makes an additional 00.00 purchase of shares" should be "The investor makes an additional 200.00 purchase of shares"

Reply | Read entire comment

Nice one. Very helpfulBy Anonymous on June 21, 2009, 1:16 pmNice one. Very helpful

Reply | Read entire comment

Nice oneBy Anonymous on March 8, 2009, 2:53 pmNice one

Reply | Read entire comment

View all comments

Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources
  • More JavaWorld articles by Robert Nielsen: