Twórz centy za pomocą BigDecimal

Aby móc pisać programy Java zajmujące się finansami, musisz wiedzieć o

BigDecimal

formatowanie klas i liczb. Pierwszym krokiem do nauczenia Cię obu tych tematów jest najpierw tworzenie

BigDecimal

obiekty. Będziemy używać

BigDecimal

klasa w

java.math

biblioteka do przechowywania wartości. Możesz utworzyć plik

BigDecimal

sprzeciwić się w następujący sposób:

BigDecimal amount = nowy BigDecimal ("1115.37"); 

W powyższym przypadku Stringargument do BigDecimalkonstruktora określa wartość utworzonego obiektu. Wartość "1115.37"może reprezentować na przykład miesięczną spłatę kredytu hipotecznego w dolarach lub saldo książeczki czekowej. Aby wyświetlić kwotę, możesz użyć metody BigDecimalklasy toString():

 System.out.println (amount.toString ()); 

Program, który tworzy i wyświetla BigDecimalkwotę, pokazano poniżej:

import java.math. *; public class Mortgage {public static void main (String [] args) {BigDecimal payment = new BigDecimal ("1115.37"); System.out.println (payment.toString ()); }}

Dane wyjściowe z powyższego programu to:

1115,37 

Formatowanie waluty

Ponieważ mamy do czynienia z pieniędzmi, dobrze byłoby, gdyby kwoty przechowywane przez BigDecimalobiekty były odpowiednio sformatowane, co dla waluty amerykańskiej zawierałoby znak dolara i przecinek jako separator tysięcy. (Informacje na temat innych walut można znaleźć w sekcji Waluta innych krajów poniżej). NumberFormatKlasy, znajdujący się w java.textbibliotece, można utworzyć odpowiedni obiekt dla amerykańskiej waluty z następującego kodu:

 NumberFormat n = NumberFormat.getCurrencyInstance (Locale.US); 

Zauważ, że Localeklasa używana jako argument getCurrencyInstance()powyższej metody znajduje się w java.utilbibliotece.

W NumberFormat„S format()metodą, będziemy używać Następnie wykonuje podwójne lub długi prymitywny jako argumentu, tak że najpierw przekręcić BigDecimalprzedmiot w doubleużywając BigDecimal” s doubleValue()sposobem:

double doublePayment = payment.doubleValue (); 

Teraz używamy metody NumberFormat' format()do stworzenia String:

 String s = n.format (doublePayment); 

Umieszczając te kroki w programie, otrzymujemy:

import java.math. *; import java.text. *; import java.util. *; public class Mortgage2 {public static void main (String [] args) {BigDecimal payment = new BigDecimal ("1115.37"); NumberFormat n = NumberFormat.getCurrencyInstance (Locale.US); double doublePayment = payment.doubleValue (); String s = n.format (doublePayment); System.out.println (s); }}

Dane wyjściowe z powyższego programu to:

115,37 

Czytelnicy powinni pamiętać, że tworzenie doublewartości wiąże się z niewielką utratą dokładności wartości. Chociaż niedokładności są zbyt małe, aby można je było zobaczyć w przykładach w tym artykule, są one widoczne w bardzo dużych ilościach. Dlatego nie można polegać na NumericFormatuzyskaniu dokładnych wyników przy bardzo dużych liczbach (około 13 lub więcej cyfr).

Waluty innych krajów

W poprzednim przykładzie Locale.USjako argument przekazany do getCurrencyInstance()metody posłużyliśmy się określeniem waluty kraju (Stany Zjednoczone), z którym będziemy pracować. Jednak Java nie ogranicza się do pracy z walutą amerykańską. Na przykład możesz użyć Locale.GERMANY, Locale.FRANCElub, Locale.ITALYaby określić waluty odpowiednio Niemiec, Francji i Włoch. Temat internacjonalizacji jest odrębnym tematem; zobacz sekcję Zasoby, aby uzyskać łącze do dodatkowych informacji.

Operacje BigDecimal

BigDecimalMetody dodawania i odjęcie liczby są add()i subtract(), odpowiednio. Na przykład, aby dodać 1115,37 i 115,37, moglibyśmy wykonać następujące czynności:

Saldo BigDecimal = nowy BigDecimal ("1115.37"); Transakcja BigDecimal = nowa BigDecimal ("115,37"); BigDecimal newBalance = balance.add (transakcja);

Obiekt BigDecimal' newBalancema teraz wartość 1 230,74. Podobnie, aby odjąć 115,37 od 1115,37, moglibyśmy użyć tego kodu:

Saldo BigDecimal = nowy BigDecimal ("1115.37"); Transakcja BigDecimal = nowa BigDecimal ("115,37"); BigDecimal newBalance2 = balance.subtract (transakcja);

Obiekt BigDecimalma newBalance2teraz wartość 1000,00. (Oczywiście, jeśli mówimy o saldach książeczki czekowej w prawdziwym życiu, subtract()metoda będzie używana znacznie częściej niż add()metoda, a całkowita kwota odejmowana od salda książeczki czekowej przekroczy całkowitą kwotę dodaną, a przynajmniej tak się często wydaje) można wykonać mnożenie i dzielenie przez BigDecimal„s multiply()i divide()metod. Mnożenie jest pokazane w następującym programie:

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 = nowy BigDecimal („0,0049”); BigDecimal d2 = d.multiply (taxRate); System.out.println ("Niesformatowany:" + d2.toString ()); NumberFormat n = NumberFormat.getCurrencyInstance (Locale.US); double money = d2.doubleValue (); String s = n.format (pieniądze); System.out.println ("Sformatowany:" + s); }}

Dane wyjściowe dla powyższego kodu pokazano poniżej:

Niesformatowany: 5.465068 Sformatowany: .46 

Zwróć uwagę na dodatkowe miejsca dziesiętne w niesformatowanym BigDecimalobiekcie w porównaniu z sformatowanym wyjściem. Ponadto sformatowanie wartości BigDecimalobiektu powoduje usunięcie ułamka - większego niż połowa -. Aby zarządzać dodatkowych miejsc dziesiętnych oraz brak zaokrąglenia, możemy użyć BigDecimal„s setScale()metody, aby określić liczbę miejsc po przecinku. Używając setScale(), musimy określić nie tylko liczbę miejsc dziesiętnych, ale także sposób, w jaki liczba zostanie zaokrąglona, ​​jeśli zaokrąglenie jest konieczne. Najpopularniejszy sposób zaokrąglania - zaokrąglanie ułamków w górę o połowę lub więcej i zaokrąglanie w dół wszystkich innych ułamków - można określić za pomocą BigDecimalstałej ' ROUND_HALF_UP. Dlatego, aby ustawić liczbę miejsc po przecinku na dwa i określić, że ułamki połówkowe i większe będą zaokrąglane w górę, możemy napisać:

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

Modyfikując powyższy program w celu dodania setScale(), mamy teraz:

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 = nowy BigDecimal („0,0049”); BigDecimal d2 = d.multiply (taxRate); d2 = d2.setScale (2, BigDecimal.ROUND_HALF_UP); System.out.println ("Niesformatowany:" + d2.toString ()); NumberFormat n = NumberFormat.getCurrencyInstance (Locale.US); double money = d2.doubleValue (); String s = n.format (pieniądze); System.out.println ("Sformatowany:" + s); }}

Teraz wynik to:

Niesformatowany: 5.47 Sformatowany: .47 

Teraz BigDecimalwartość jest zaokrąglana do dwóch cyfr, zaokrąglając ją w górę, a sformatowana Stringpoprawnie wyświetla zaokrągloną wartość. Inne stałe przydatne w zaokrąglaniu to ROUND_HALF_DOWNi ROUND_HALF_EVEN. Pierwsza ROUND_HALF_DOWNzaokrągla ułamki połowy i poniżej, a wszystkie pozostałe w górę. Drugi ROUND_HALF_EVENzaokrągla połowę ułamków do liczby parzystej (np. 2,5 zaokrągla do 2, a 3,5 zaokrągla do 4), a ułamki większe lub mniejsze niż połowa do najbliższej liczby całkowitej. Podczas dzielenia BigDecimalobiektów musimy określić sposób zaokrąglenia wyniku. W tym artykule zaokrąglimy połówki w górę. Poniższy program przedstawia przykładowy podział:

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 = nowy 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 (pieniądze); System.out.println (s); }}

Dane wyjściowe z powyższego programu to:

7.18 

Obliczanie odsetek

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:

Number of shares = 773.763 Account value = ,031.66 

More formatting

In the above example, the number of shares happens to be less than 1,000. If it had been greater than 1,000, the program would have outputted the number without a comma to separate the thousands place from the other digits. We can create a NumberFormat object to format numbers in the US style (commas separate thousands, periods separate decimals) by using:

NumberFormat n2 = NumberFormat.getInstance(Locale.US); 

Modifying the previous program to increase the number of shares to more than 1,000 and to display the number of shares formatted as we desire, we have:

import java.math.*; import java.text.*; import java.util.*; public class Mutual2 { public static void main(String[] args) { BigDecimal shares = new BigDecimal("1754.495"); BigDecimal purchaseAmount = new BigDecimal("2000.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); NumberFormat n2 = NumberFormat.getInstance(Locale.US); double dShares = shares.doubleValue(); String sShares = n2.format(dShares); System.out.println("Number of shares = " + sShares); System.out.println("Account value = " + sAccountValue); } } 

The modified version (directly above) now outputs:

Number of shares = 1,947.173 Account value = 0,211.66 

Caveats

If you are writing a program that you or others will depend on for financial calculations, it makes sense to be as careful as possible. First, test your program thoroughly. Second, consult professionals, such as accountants, if you have any doubt as to the correct formula, rounding rule, or any other monetary aspect.

Summing up

BigDecimal objects, which represent values, can be added, subtracted, multiplied, and divided. While you can display BigDecimal objects using the toString() method, it is often preferable to create a NumberFormat object to format doubles obtained from BigDecimal. Now you can add the value of making simple interest calculations and mutual fund transactions in your Java programs.

Robert Nielsen jest programistą Java 2 z certyfikatem Sun Certified. Posiada tytuł magistra pedagogiki, specjalizujący się w nauczaniu wspomaganym komputerowo, a od kilku lat prowadzi zajęcia z informatyki. Opublikował także artykuły o tematyce komputerowej w różnych czasopismach.