CodeGym/Java blog/Tilfældig/BigDecimal i Java
John Squirrels
Niveau
San Francisco

BigDecimal i Java

Udgivet i gruppen
Hej! I dagens lektion vil vi tale om store tal. Nej, jeg mener RIGTIG STORT. Vi har tidligere gentagne gange stødt på tabellen over værdiintervaller for primitive datatyper. Det ser sådan ud:
Primitiv type Størrelse i hukommelsen Værdiinterval
byte 8 bit -128 til 127
kort 16 bit -32768 til 32767
char 16 bit 0 til 65536
int 32 bit -2147483648 til 2147483647
lang 64 bit -9223372036854775808 til 9223372036854775807
flyde 32 bit (2 i potens af -149) til ((2 i potens af -23) * 2 i potens af 127)
dobbelt 64 bit (-2 i potens af 63) til ((2 i potens af 63) - 1)
boolesk 8 (når det bruges i arrays), 32 (når det ikke bruges i arrays) sandt eller falsk
Den mest rummelige heltalsdatatype er den lange . Når det kommer til flydende kommatal, er det det dobbelte . Men hvad nu hvis det antal, vi har brug for, er så stort, at det ikke engang passer ind i en lang ? Den lange datatype har et ret stort udvalg af mulige værdier, men den er stadig begrænset til 64 bit. Hvad skal vi finde på, hvis vores meget store tal kræver 100 bit? Heldigvis behøver vi ikke finde på noget. For tilfælde som dette har Java to specialklasser: BigInteger (for heltal) og BigDecimal(for flydende kommatal). Hvad gør dem specielle? Først og fremmest har de i teorien ingen maksimal størrelse. Vi siger "i teorien", for der er ingen computere med uendelig hukommelse. Og hvis dit program opretter et tal, der er større end mængden af ​​tilgængelig hukommelse, så virker programmet selvfølgelig ikke. Men sådanne tilfælde er usandsynlige. Som et resultat kan vi sige, at BigInteger og BigDecimal kan repræsentere tal af praktisk talt ubegrænset størrelse. Hvad bruges disse klasser til? Først og fremmest til beregninger med ekstremt strenge krav til nøjagtighed. For eksempel kan menneskeliv afhænge af nøjagtigheden af ​​beregninger i nogle programmer (f.eks. software, der styrer flyvemaskiner, raketter eller medicinsk udstyr). Så hvis den 150. decimal er vigtig, så er BigDecimaler det bedste valg. Derudover bruges objekter af denne klasse ofte i finansverdenen, hvor nøjagtig beregning af selv de mindste værdier også er ekstremt vigtig. Hvordan arbejder du med BigInteger og BigDecimal- objekter, og har du brug for at vide om dem? Objekter af disse klasser er oprettet som dette:
public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
       System.out.println(decimal);
   }
}
At sende en streng til konstruktøren er kun en mulig mulighed. Her bruger vi strenge, fordi vores tal overstiger de maksimale værdier for lang og dobbelt , og vi har brug for en måde at forklare compileren på, hvilket tal vi vil oprette :) Du skal blot sende tallet 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 til konstruktøren vil ikke virke: Java vil forsøge at proppe det beståede nummer ind i en af ​​de primitive datatyper, men det passer ikke ind i nogen af ​​dem. Derfor er det en god mulighed at bruge en streng til at sende det ønskede nummer. Begge klasser kan automatisk udtrække numeriske værdier fra de beståede strenge. Et andet vigtigt punkt at huske på, når du arbejder med klasser med store tal, er, at deres objekter er uforanderlige ( Immutable ). Du er allerede bekendt med uforanderlighed takket være din erfaring med String -klassen og wrapper-klasserne for primitive typer (heltal, lang, osv.).
import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       integer.add(BigInteger.valueOf(33333333));
       System.out.println(integer);

   }
}
Konsoludgang:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Som du ville forvente, har vores nummer ikke ændret sig. For at udføre tilføjelsesoperationen skal du oprette et nyt objekt for at modtage resultatet af operationen.
import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigInteger result = integer.add(BigInteger.valueOf(33333333));
       System.out.println(result);

   }
}
Konsoludgang:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Se, nu fungerer alt som det skal :) Har du forresten lagt mærke til hvor usædvanlig tilføjelsesoperationen ser ud?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Dette er et andet vigtigt punkt. Klasser med store tal bruger ikke + - * / operatorerne. I stedet giver de et sæt metoder. Lad os stifte bekendtskab med de vigtigste (som altid kan du finde en komplet liste over metoder i Oracle-dokumentationen: her og her ).
  1. metoder til aritmetiske operationer: add() , subtract() , multiplicer() , divide() . Disse metoder bruges til at udføre henholdsvis addition, subtraktion, multiplikation og division.

  2. doubleValue() , intValue() , floatValue() , longValue() osv. bruges til at konvertere et stort tal til en af ​​Javas primitive typer. Vær forsigtig, når du bruger disse metoder. Glem ikke forskellene i bitstørrelse!

    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
    
           long result = integer.longValue();
           System.out.println(result);
    
       }
    }

    Konsoludgang:

    8198552921648689607
  3. min() og max() lader dig finde minimums- og maksimumværdien af ​​to store tal.
    Bemærk, at disse metoder ikke er statiske!

    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
           BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222");
    
           System.out.println(integer.max(integer2));
    
       }
    }

    Konsoludgang:

    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

BigDecimal afrundingsadfærd

Dette emne har sit eget separate afsnit, da afrunding af store tal og konfigurering af afrundingsadfærd ikke er så enkelt. Du kan bruge metoden setScale() til at indstille antallet af decimaler for en BigDecimal . Antag for eksempel, at vi ønsker, at tallet 111.5555555555 skal have tre cifre efter decimaltegnet. Vi kan dog ikke opnå det, vi ønsker, ved at overføre tallet 3 som et argument til setScale()- metoden. Som nævnt ovenfor, BigDecimaler til at repræsentere tal med strenge krav til beregningspræcision. I sin nuværende form har vores nummer 10 cifre efter decimalkommaet. Vi vil droppe 7 af dem og kun beholde 3. Derfor skal vi ud over tallet 3 passere afrundingstilstanden. BigDecimal har i alt 8 afrundingstilstande. Det er en del! Men hvis du virkelig har brug for at finjustere præcisionen af ​​dine beregninger, har du alt, hvad du behøver. Så her er de 8 afrundingstilstande, der tilbydes af BigDecimal :
  1. ROUND_CEILING — runder op

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN — runder mod nul

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR — runder ned

    111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555

  4. ROUND_HALF_UP — runder op, hvis tallet efter decimaltegnet >= 0,5

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN — runder op, hvis tallet efter decimaltegnet > 0,5

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN — afrunding afhænger af tallet til venstre for decimaltegnet. Hvis tallet til venstre er lige, vil afrundingen være nedad. Hvis tallet til venstre for decimaltegnet er ulige, vil afrundingen være opad.

    2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2

    Tallet til venstre for decimalen er 2 (lige). Tallet er rundet ned. Vi vil have 0 decimaler, så resultatet er 2.

    3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4

    Tallet til venstre for decimaltegnet er 3 (ulige). Tallet rundes op. Vi vil have 0 decimaler, så resultatet er 4.

  7. ROUND_UNNECCESSARY — Denne tilstand bruges, når du skal overføre en afrundingstilstand til en metode, men tallet behøver ikke at blive afrundet. Hvis du forsøger at runde et tal med ROUND_UNNECCESSARY-tilstanden indstillet, kastes en ArithmeticException.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP — runder væk fra nul.

    111.5551 -> setScale(3, ROUND_UP) -> 111.556

Sammenligner store tal

Dette er også vigtigt. Du vil huske, at vi bruger equals()- metoden til at sammenligne objekter i Java. Implementeringen leveres enten af ​​selve sproget (til standard Java-klasser) eller tilsidesættes af programmøren. Men i tilfælde af BigDecimal- objekter anbefales det ikke at bruge equals()- metoden til sammenligninger. Dette skyldes, at metoden BigDecimal.equals() kun returnerer sand, hvis de 2 tal har samme værdi og skala: Lad os sammenligne adfærden for equals()- metoden for klasserne Double og BigDecimal :
import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       Double a = 1.5;
       Double b = 1.50;

       System.out.println(a.equals(b));

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.equals(y));

   }
}
Konsoludgang:
true
false
Som du kan se, for BigDecimal viste tallene 1,5 og 1,50 sig at være ulige! Dette var netop på grund af detaljerne i implementeringen af ​​equals() -metoden i BigDecimal- klassen. For en mere nøjagtig sammenligning af to BigDecimal- objekter er det bedre at bruge compareTo()- metoden:
import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.compareTo(y));

   }
}
Konsoludgang:
0
CompareTo () -metoden returnerede 0, hvilket betyder, at 1,5 og 1,50 er ens. Og det er det resultat, vi forventede! :) Det afslutter vores lektion i dag. Nu er det tid til at vende tilbage til opgaverne! :)
Kommentarer
  • Populær
  • Ny
  • Gammel
Du skal være logget ind for at skrive en kommentar
Denne side har ingen kommentarer endnu