Szukaj…


Wprowadzenie

Klasa BigDecimal zapewnia operacje arytmetyczne (dodawanie, odejmowanie, mnożenie, dzielenie), manipulowanie skalą, zaokrąglanie, porównywanie, mieszanie i konwersję formatu. BigDecimal reprezentuje niezmienne liczby dziesiętne ze znakiem o dowolnej dokładności. Tę klasę należy stosować w celu obliczeń o wysokiej precyzji.

Obiekty BigDecimal są niezmienne

Jeśli chcesz obliczyć za pomocą BigDecimal, musisz użyć zwróconej wartości, ponieważ obiekty BigDecimal są niezmienne:

BigDecimal a = new BigDecimal("42.23");
BigDecimal b = new BigDecimal("10.001");

a.add(b); // a will still be 42.23

BigDecimal c = a.add(b); // c will be 52.231 

Porównywanie BigDecimals

Do porównania BigDecimals należy użyć metody compareTo :

BigDecimal a = new BigDecimal(5);
a.compareTo(new BigDecimal(0));    // a is greater, returns 1
a.compareTo(new BigDecimal(5));    // a is equal, returns 0
a.compareTo(new BigDecimal(10));   // a is less, returns -1

Zwykle nie należy używać equals sposób, ponieważ uważa, dwa BigDecimals równe tylko wtedy, gdy są równe pod względem wartości, a także skala:

BigDecimal a = new BigDecimal(5);
a.equals(new BigDecimal(5));       // value and scale are equal, returns true
a.equals(new BigDecimal(5.00));    // value is equal but scale is not, returns false

Operacje matematyczne z BigDecimal

Ten przykład pokazuje, jak wykonywać podstawowe operacje matematyczne za pomocą BigDecimals.

1.Dodatek

BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = a + b
BigDecimal result = a.add(b);
System.out.println(result);

Wynik: 12

2. Odejmowanie

BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = a - b
BigDecimal result = a.subtract(b);
System.out.println(result);

Wynik: -2

3. Mnożenie

Po pomnożeniu dwóch BigDecimal wynik będzie miał skalę równą sumie skal operandów.

BigDecimal a = new BigDecimal("5.11");
BigDecimal b = new BigDecimal("7.221");

//Equivalent to result = a * b
BigDecimal result = a.multiply(b);
System.out.println(result);

Wynik: 36,89931

Aby zmienić skalę wyniku, użyj przeciążonej metody mnożenia, która pozwala przekazać MathContext - obiekt opisujący reguły dla operatorów, w szczególności tryb precyzji i zaokrąglania wyniku. Więcej informacji na temat dostępnych trybów zaokrąglania można znaleźć w dokumentacji Oracle.

BigDecimal a = new BigDecimal("5.11");
BigDecimal b = new BigDecimal("7.221");

MathContext returnRules = new MathContext(4, RoundingMode.HALF_DOWN);

//Equivalent to result = a * b
BigDecimal result = a.multiply(b, returnRules);
System.out.println(result);

Wynik: 36,90

4. Podział

Podział jest nieco bardziej skomplikowany niż inne operacje arytmetyczne, na przykład rozważ poniższy przykład:

BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

BigDecimal result = a.divide(b);
System.out.println(result);

Spodziewalibyśmy się, że da to coś podobnego do: 0.7142857142857143, ale otrzymalibyśmy:

Wynik: java.lang.ArithmeticException : Niekończące się rozwinięcie dziesiętne; brak dokładnego reprezentatywnego wyniku dziesiętnego.

Działałoby to doskonale, gdy wynikiem byłby wynik dziesiętny kończący, gdybym chciał podzielić 5 przez 2, ale dla liczb, które po podzieleniu dawałyby wynik nie kończący, otrzymalibyśmy ArithmeticException . W scenariuszu ze świata rzeczywistego nie można przewidzieć wartości, które wystąpiłyby podczas podziału, dlatego musimy określić skalę i tryb zaokrąglania dla podziału BigDecimal. Więcej informacji na temat trybu skalowania i zaokrąglania można znaleźć w dokumentacji Oracle .

Na przykład mógłbym zrobić:

BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = a / b (Upto 10 Decimal places and Round HALF_UP)
BigDecimal result = a.divide(b,10,RoundingMode.HALF_UP);
System.out.println(result);

Wynik: 0,7142857143

5. Remainder lub moduł

BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = a % b
BigDecimal result = a.remainder(b);
System.out.println(result);

Wynik: 5

6. moc

BigDecimal a = new BigDecimal("5");

//Equivalent to result = a^10    
BigDecimal result = a.pow(10);
System.out.println(result);

Wynik: 9765625

7.Maks

BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = MAX(a,b) 
BigDecimal result = a.max(b);
System.out.println(result);

Wynik: 7

8. min

BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = MIN(a,b) 
BigDecimal result = a.min(b);
System.out.println(result);

Wynik: 5

9. Przesuń punkt w lewo

BigDecimal a = new BigDecimal("5234.49843776");

//Moves the decimal point to 2 places left of current position
BigDecimal result = a.movePointLeft(2);
System.out.println(result);

Wynik: 52,3449843776

10. Przesuń punkt w prawo

BigDecimal a = new BigDecimal("5234.49843776");

//Moves the decimal point to 3 places right of current position
BigDecimal result = a.movePointRight(3);
System.out.println(result);

Wynik: 5234498,43776

Istnieje wiele innych opcji i kombinacji parametrów dla wyżej wymienionych przykładów (na przykład istnieje 6 wariantów metody dzielenia), ten zestaw jest niewyczerpującą listą i obejmuje kilka podstawowych przykładów.

Używanie BigDecimal zamiast float

Ze względu na sposób, w jaki typ zmiennoprzecinkowy jest reprezentowany w pamięci komputera, wyniki operacji wykorzystujących ten typ mogą być niedokładne - niektóre wartości są przechowywane jako przybliżone. Dobrym tego przykładem są obliczenia pieniężne. Jeśli konieczna jest wysoka precyzja, należy zastosować inne typy. np. Java 7 zapewnia BigDecimal.

import java.math.BigDecimal;

public class FloatTest {

public static void main(String[] args) {
    float accountBalance = 10000.00f;
    System.out.println("Operations using float:");
    System.out.println("1000 operations for 1.99");
    for(int i = 0; i<1000; i++){
        accountBalance -= 1.99f;
    }
    System.out.println(String.format("Account balance after float operations: %f", accountBalance));
    
    BigDecimal accountBalanceTwo = new BigDecimal("10000.00");
    System.out.println("Operations using BigDecimal:");
    System.out.println("1000 operations for 1.99");
    BigDecimal operation = new BigDecimal("1.99");
    for(int i = 0; i<1000; i++){
        accountBalanceTwo = accountBalanceTwo.subtract(operation);
    }
    System.out.println(String.format("Account balance after BigDecimal operations: %f", accountBalanceTwo));
}

Dane wyjściowe tego programu to:

Operations using float:
1000 operations for 1.99
Account balance after float operations: 8009,765625
Operations using BigDecimal:
1000 operations for 1.99
Account balance after BigDecimal operations: 8010,000000

Dla salda początkowego 10000,00 po 1000 operacji dla 1,99 spodziewamy się, że saldo wyniesie 8010,00. Użycie typu float daje nam odpowiedź około 8009,77, co jest niedopuszczalnie niedokładne w przypadku obliczeń pieniężnych. Korzystanie z BigDecimal daje nam właściwy wynik.

BigDecimal.valueOf ()

Klasa BigDecimal zawiera wewnętrzny bufor często używanych liczb, np. Od 0 do 10. Metody BigDecimal.valueOf () są dostarczane zamiast konstruktorów o podobnych parametrach typu, tj. W poniższym przykładzie a jest preferowane zamiast b.

BigDecimal a = BigDecimal.valueOf(10L); //Returns cached Object reference
BigDecimal b = new BigDecimal(10L); //Does not return cached Object reference

BigDecimal a = BigDecimal.valueOf(20L); //Does not return cached Object reference
BigDecimal b = new BigDecimal(20L); //Does not return cached Object reference


BigDecimal a = BigDecimal.valueOf(15.15); //Preferred way to convert a double (or float) into a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the result of using Double.toString(double)
BigDecimal b = new BigDecimal(15.15); //Return unpredictable result

Inicjalizacja BigDecimals o wartości zero, jeden lub dziesięć

BigDecimal zapewnia właściwości statyczne dla liczb zero, jeden i dziesięć. Dobrą praktyką jest używanie ich zamiast faktycznych liczb:

Używając właściwości statycznych, unikniesz niepotrzebnej instancji, a także literał w kodzie zamiast „magicznej liczby”.

//Bad example:
BigDecimal bad0 = new BigDecimal(0);
BigDecimal bad1 = new BigDecimal(1);
BigDecimal bad10 = new BigDecimal(10);

//Good Example:
BigDecimal good0 = BigDecimal.ZERO;
BigDecimal good1 = BigDecimal.ONE;
BigDecimal good10 = BigDecimal.TEN;


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow