CodeGym/Java-blogg/Tilfeldig/BigDecimal i Java
John Squirrels
Nivå
San Francisco

BigDecimal i Java

Publisert i gruppen
Hei! I dagens leksjon skal vi snakke om store tall. Nei, jeg mener VELDIG STOR. Vi har tidligere gjentatte ganger møtt tabellen over verdiområder for primitive datatyper. Det ser slik ut:
Primitiv type Størrelse i minnet Verdiområde
byte 8 bit -128 til 127
kort 16 bit -32768 til 32767
røye 16 bit 0 til 65536
int 32 biter -2147483648 til 2147483647
lang 64 bit -9223372036854775808 til 9223372036854775807
flyte 32 biter (2 i potens av -149) til ((2 i potens av -23) * 2 i potens av 127)
dobbelt 64 bit (-2 i potens av 63) til ((2 i potens av 63) - 1)
boolsk 8 (når brukt i arrays), 32 (når ikke brukt i arrays) sant eller usant
Den romsligste heltallsdatatypen er den lange . Når det kommer til flyttall, er det det doble . Men hva om antallet vi trenger er så stort at det ikke engang passer inn i en lang ? Den lange datatypen har et ganske stort utvalg av mulige verdier, men den er fortsatt begrenset til 64 biter. Hva må vi finne på hvis vårt Very Large Number krever 100 bits? Heldigvis trenger vi ikke finne på noe. For tilfeller som dette har Java to spesialklasser: BigInteger (for heltall) og BigDecimal(for flyttall). Hva gjør dem spesielle? Først av alt, i teorien har de ingen maksimal størrelse. Vi sier "i teorien", fordi det ikke finnes datamaskiner med uendelig minne. Og hvis programmet ditt lager et tall som er større enn mengden tilgjengelig minne, vil programmet selvfølgelig ikke fungere. Men slike tilfeller er usannsynlige. Som et resultat kan vi si at BigInteger og BigDecimal kan representere tall av tilnærmet ubegrenset størrelse. Hva brukes disse timene til? Først og fremst for beregninger med ekstremt strenge krav til nøyaktighet. For eksempel kan menneskeliv avhenge av nøyaktigheten av beregninger i enkelte programmer (f.eks. programvare som kontrollerer fly, raketter eller medisinsk utstyr). Så hvis 150. desimal er viktig, så BigDesimaler det beste valget. I tillegg brukes ofte gjenstander av denne klassen i finansverdenen, hvor nøyaktig beregning av selv de minste verdiene også er ekstremt viktig. Hvordan jobber du med BigInteger og BigDecimal- objekter og trenger du å vite om dem? Objekter av disse klassene er laget slik:
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);
   }
}
Å sende en streng til konstruktøren er bare ett mulig alternativ. Her bruker vi strenger, fordi tallene våre overskrider maksimumsverdiene for lang og dobbel , og vi trenger en måte å forklare kompilatoren på hvilket nummer vi vil lage :) Bare å sende inn tallet 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 til konstruktøren vil ikke fungere: Java vil prøve å stappe det beståtte nummeret inn i en av de primitive datatypene, men det vil ikke passe inn i noen av dem. Derfor er det et godt alternativ å bruke en streng for å sende ønsket nummer. Begge klassene kan automatisk trekke ut numeriske verdier fra de beståtte strengene. Et annet viktig poeng å huske når du arbeider med store tallklasser er at objektene deres er uforanderlige ( Immutable ). Du er allerede kjent med uforanderlighet takket være din erfaring med String -klassen og wrapper-klassene for primitive typer (heltall, lang, etc.).
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);

   }
}
Konsoll utgang:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Som du forventer, er nummeret vårt ikke endret. For å utføre tilleggsoperasjonen må du opprette et nytt objekt for å motta resultatet av operasjonen.
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);

   }
}
Konsoll utgang:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Se, nå fungerer alt som det skal :) La du forresten merke til hvor uvanlig addisjonsoperasjonen ser ut?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Dette er et annet viktig poeng. Klasser med store tall bruker ikke + - * /-operatorene. I stedet gir de et sett med metoder. La oss bli kjent med de viktigste (som alltid kan du finne en fullstendig liste over metoder i Oracle-dokumentasjonen: her og her ).
  1. metoder for aritmetiske operasjoner: add() , subtrahere() , multiplisere() , divide() . Disse metodene brukes til å utføre henholdsvis addisjon, subtraksjon, multiplikasjon og divisjon.

  2. doubleValue() , intValue() , floatValue() , longValue() osv. brukes til å konvertere et stort tall til en av Javas primitive typer. Vær forsiktig når du bruker disse metodene. Ikke glem forskjellene 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);
    
       }
    }

    Konsoll utgang:

    8198552921648689607
  3. min() og max() lar deg finne minimums- og maksimumsverdien til to store tall.
    Merk at disse metodene 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));
    
       }
    }

    Konsoll utgang:

    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

BigDesimal avrundingsadferd

Dette emnet har sin egen del, siden avrunding av store tall og konfigurering av avrundingsatferd ikke er så enkelt. Du kan bruke setScale() -metoden til å angi antall desimaler for en BigDecimal . Anta for eksempel at vi vil at tallet 111.5555555555 skal ha tre sifre etter desimaltegn. Vi kan imidlertid ikke oppnå det vi ønsker ved å sende tallet 3 som et argument til setScale()- metoden. Som nevnt ovenfor, BigDecimaler for å representere tall med strenge krav til beregningspresisjon. I sin nåværende form har nummeret vårt 10 sifre etter desimaltegn. Vi ønsker å slippe 7 av dem og bare beholde 3. I tillegg til tallet 3 må vi derfor passere avrundingsmodusen. BigDecimal har totalt 8 avrundingsmoduser. Det er mye! Men hvis du virkelig trenger å finjustere nøyaktigheten av beregningene dine, har du alt du trenger. Så, her er de 8 avrundingsmodusene som tilbys av BigDecimal :
  1. ROUND_CEILING — runder opp

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN — runder mot null

    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 opp hvis tallet etter desimaltegn >= 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 opp hvis tallet etter desimaltegn > 0,5

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN — avrunding avhenger av tallet til venstre for desimaltegn. Hvis tallet til venstre er partall, vil avrundingen være nedover. Hvis tallet til venstre for desimaltegnet er oddetall, vil avrundingen være oppover.

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

    Tallet til venstre for desimalplassen er 2 (part). Tallet rundes ned. Vi vil ha 0 desimaler, så resultatet er 2.

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

    Tallet til venstre for desimaltegnet er 3 (oddetall). Tallet rundes opp. Vi vil ha 0 desimaler, så resultatet er 4.

  7. ROUND_UNNECCESSARY — Denne modusen brukes når du må sende en avrundingsmodus til en metode, men tallet trenger ikke å avrundes. Hvis du prøver å runde av et tall med ROUND_UNNECCESSARY-modusen satt, blir det kastet et ArithmeticException.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP — runder bort fra null.

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

Sammenligner store tall

Dette er også viktig. Du vil huske at vi bruker equals()- metoden for å sammenligne objekter i Java. Implementeringen leveres enten av selve språket (for standard Java-klasser) eller overstyrt av programmereren. Men når det gjelder BigDecimal- objekter, anbefales det ikke å bruke equals()- metoden for sammenligninger. Dette er fordi BigDecimal.equals()- metoden returnerer sann bare hvis de 2 tallene har samme verdi og skala: La oss sammenligne oppførselen til equals()- metoden for Double og BigDecimal -klassene:
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));

   }
}
Konsoll utgang:
true
false
Som du kan se, for BigDecimal , viste tallene 1,5 og 1,50 seg å være ulik! Dette var nettopp på grunn av spesifikasjonene ved implementeringen av equals() -metoden i BigDecimal- klassen. For en mer nøyaktig sammenligning av to BigDecimal- objekter, er det bedre å bruke 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));

   }
}
Konsoll utgang:
0
CompareTo () -metoden returnerte 0, som betyr at 1,5 og 1,50 er like. Og dette er resultatet vi forventet! :) Det avslutter leksjonen vår i dag. Nå er det på tide å komme tilbake til oppgavene! :)
Kommentarer
  • Populær
  • Ny
  • Gammel
Du må være pålogget for å legge igjen en kommentar
Denne siden har ingen kommentarer ennå