Sök…


Introduktion

BigDecimal- klassen tillhandahåller operationer för aritmetik (lägg till, subtrahera, multiplicera, dela), skala manipulation, avrundning, jämförelse, hashing och formatkonvertering. BigDecimal representerar oföränderligt, godtyckligt preciserat decimaltal. Denna klass ska användas för att beräkna hög precision.

BigDecimal-objekt är oföränderliga

Om du vill beräkna med BigDecimal måste du använda det returnerade värdet eftersom BigDecimal-objekt är oföränderliga:

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 

Jämför BigDecimals

Metoden compareTo bör användas för att jämföra BigDecimals :

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

Vanligtvis bör du inte använda metoden equals eftersom den anser att två BigDecimals endast är lika om de är lika i värde och också 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

Matematiska operationer med BigDecimal

Detta exempel visar hur du utför grundläggande matematiska operationer med hjälp av BigDecimals.

1.Addition

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

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

Resultat: 12

2.Subtraction

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

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

Resultat: -2

3.Multiplication

När man multiplicerar två BigDecimal resultatet att ha skala lika med summan av skalorna på operander.

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);

Resultat: 36.89931

För att ändra resultatets skala använder du den överbelastade multiplikationsmetoden som gör det möjligt att passera MathContext - ett objekt som beskriver reglerna för operatörer, särskilt resultatets precision och avrundningsläge. För mer information om tillgängliga avrundningslägen, se Oracle-dokumentationen.

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);

Resultat: 36,90

4.Division

Uppdelning är lite mer komplicerad än de andra aritmetiska operationerna, tänk exempelvis nedanstående exempel:

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

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

Vi förväntar oss att detta skulle ge något som liknar: 0.7142857142857143, men vi skulle få:

Resultat: java.lang.ArithmeticException: Icke avslutande decimalutvidgning; inget exakt representativt decimalresultat.

Detta skulle fungera perfekt när resultatet skulle bli en avslutande decimal säga om jag ville dela 5 med 2, men för de siffror som vid delning skulle ge ett icke avslutande resultat skulle vi få en ArithmeticException . I den verkliga scenariot kan man inte förutsäga de värden som skulle uppstå under uppdelningen, så vi måste specificera skalan och avrundningsläget för BigDecimal-divisionen. Mer information om skala och avrundningsläge finns i Oracle-dokumentationen .

Till exempel kan jag göra:

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);

Resultat: 0.7142857143

5. Rest eller modul

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

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

Resultat: 5

6.Power

BigDecimal a = new BigDecimal("5");

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

Resultat: 9765625

7.Max

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);

Resultat: 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);

Resultat: 5

9. Flytta pekar till vänster

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);

Resultat: 52.3449843776

10. Flytta pekar till höger

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);

Resultat: 5234498.43776

Det finns många fler alternativ och kombination av parametrar för ovan nämnda exempel (till exempel finns det 6 varianter av delningsmetoden), denna uppsättning är en icke uttömmande lista och täcker några grundläggande exempel.

Använda BigDecimal istället för float

På grund av att flottörtypen representeras i datorminne kan resultat av operationer som använder denna typ vara felaktiga - vissa värden lagras som ungefärliga. Bra exempel på detta är monetära beräkningar. Om hög precision är nödvändig bör andra typer användas. t.ex. Java 7 tillhandahåller 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));
}

Output från detta program är:

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

För en startbalans på 10000,00, efter 1000 operationer för 1,99, förväntar vi oss att saldot blir 8010,00. Användning av flottörtypen ger oss ett svar på cirka 8009,77, vilket är oacceptabelt upresist när det gäller monetära beräkningar. Att använda BigDecimal ger oss rätt resultat.

BigDecimal.valueOf ()

BigDecimal-klassen innehåller en intern cache av ofta använda siffror, t.ex. 0 till 10. BigDecimal.valueOf () -metoderna tillhandahålls företrädesvis för konstruktörer med parametrar av liknande typ, dvs i exemplet nedan föredras a 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

Initialisering av BigDecimals med värdet noll, en eller tio

BigDecimal tillhandahåller statiska egenskaper för siffrorna noll, en och tio. Det är bra att använda dessa istället för att använda de faktiska siffrorna:

Genom att använda de statiska egenskaperna undviker du en onödig instans, du har också en bokstavlig kod i stället för ett "magiskt nummer".

//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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow