CodeGym/Java blog/Véletlen/BigDecimal Java nyelven
John Squirrels
Szint
San Francisco

BigDecimal Java nyelven

Megjelent a csoportban
Szia! A mai leckében nagy számokról fogunk beszélni. Nem, úgy értem, IGAZÁN NAGY. Korábban többször találkoztunk a primitív adattípusok értéktartományainak táblázatával. Ez így néz ki:
Primitív típus Méret a memóriában Értéktartomány
byte 8 bites -128-127
rövid 16 bites -32768-32767
char 16 bites 0-tól 65536-ig
int 32 bites -2147483648-2147483647
hosszú 64 bites -9223372036854775808-9223372036854775807
úszó 32 bites (2-től -149 hatványáig) ((2-től -23 hatványáig) * 2-től 127 hatványáig)
kettős 64 bites (-2 a 63 hatványához) - ((2 a 63 hatványához) - 1)
logikai érték 8 (ha tömbökben használják), 32 (ha nem tömbben használják) igaz vagy hamis
A legtágasabb egész adattípus a long . Ha lebegőpontos számokról van szó, akkor ez a dupla . De mi van akkor, ha a szükséges szám olyan nagy, hogy nem is fér bele egy hosszúba ? A Long adattípusnak meglehetősen nagy a lehetséges értéktartománya, de még mindig 64 bitre korlátozódik. Mit kell kitalálnunk, ha a nagyon nagy számunkhoz 100 bit szükséges? Szerencsére nem kell kitalálnunk semmit. Az ilyen esetekben a Java két speciális osztályt tartalmaz: BigInteger (egész számokhoz) és BigDecimal(lebegőpontos számokhoz). Mitől különlegesek? Először is, elméletileg nincs maximális méretük. Azt mondjuk, hogy "elméletben", mert nincs végtelen memóriával rendelkező számítógép. És ha a program a rendelkezésre álló memória mennyiségénél nagyobb számot hoz létre, akkor a program természetesen nem fog működni. De az ilyen esetek nem valószínűek. Ennek eredményeként azt mondhatjuk, hogy a BigInteger és a BigDecimal gyakorlatilag korlátlan méretű számokat tud reprezentálni. Mire használják ezeket az osztályokat? Mindenekelőtt rendkívül szigorú pontossági követelményeket támasztó számításokhoz. Például az emberi élet függhet egyes programok (pl. repülőgépeket, rakétákat vagy orvosi berendezéseket vezérlő szoftverek) számításainak pontosságától. Tehát ha a 150. tizedesjegy fontos, akkor a BigDecimala legjobb választás. Emellett az ebbe az osztályba tartozó tárgyakat gyakran használják a pénzügyek világában is, ahol a legkisebb értékek pontos kiszámítása is rendkívül fontos. Hogyan dolgozik BigInteger és BigDecimal objektumokkal, és tudnia kell róluk? Ezen osztályok objektumai a következőképpen jönnek létre:
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);
   }
}
Egy karakterlánc átadása a konstruktornak csak egy lehetséges lehetőség. Itt karakterláncokat használunk, mert a számaink meghaladják a long és a double maximális értékét , és el kell magyaráznunk a fordítónak, hogy melyik számot szeretnénk létrehozni :) 1111111111111111111111111111111111111111111111111111111111111111111111111111 a konstruktorhoz nem fog működni: a Java megpróbálja belezsúfolni az átadott számot valamelyik primitív adattípusba, de egyikbe sem fér bele. Ezért jó megoldás egy karakterlánc használata a kívánt szám átadására. Mindkét osztály képes automatikusan számértékeket kinyerni az átadott karakterláncokból. Egy másik fontos szempont, amelyet meg kell jegyeznünk, amikor nagyszámú osztályokkal dolgozunk, az az, hogy objektumaik megváltoztathatatlanok ( Immutable ). A String osztály és a primitív típusok (Integer, Long stb.) wrapper osztályaival kapcsolatos tapasztalatainak köszönhetően már ismeri a megváltoztathatatlanságot .
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);

   }
}
Konzol kimenet:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Ahogy az várható volt, számunk nem változott. Az összeadási művelet végrehajtásához létre kell hoznia egy új objektumot, amely megkapja a művelet eredményét.
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);

   }
}
Konzol kimenet:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Na látod, most már minden úgy működik, ahogy kell :) Egyébként észrevetted, milyen szokatlanul néz ki az összeadási művelet?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Ez egy másik fontos szempont. A nagyszámú osztályok nem használják a + - * / operátorokat. Ehelyett módszereket kínálnak. Ismerkedjünk meg a főbbekkel (mint mindig, a módszerek teljes listáját az Oracle dokumentációjában találod: itt és itt ).
  1. metódusok az aritmetikai műveletekhez: összeadás() , kivonás() , szorzás() , osztás() . Ezeket a módszereket az összeadás, kivonás, szorzás és osztás végrehajtására használják.

  2. doubleValue() , intValue() , floatValue() , longValue() stb. a nagy számok Java primitív típusaivá alakítására szolgál. Legyen óvatos, amikor ezeket a módszereket használja. Ne feledkezzünk meg a bitméret különbségeiről sem!

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

    Konzol kimenet:

    8198552921648689607
  3. A min() és max() segítségével megtalálhatja két nagy szám minimális és maximális értékét.
    Vegye figyelembe, hogy ezek a módszerek nem statikusak!

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

    Konzol kimenet:

    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

BigDecimális kerekítési viselkedés

Ennek a témának külön szakasza van, mivel a nagy számok kerekítése és a kerekítési viselkedés beállítása nem olyan egyszerű. A setScale() metódussal beállíthatja a BigDecimal tizedesjegyeinek számát . Tegyük fel például, hogy azt szeretnénk, hogy a 111.5555555555 szám három számjegyből álljon a tizedesvessző után. Azonban nem érhetjük el, amit akarunk, ha a 3-as számot argumentumként adjuk át a setScale() metódusnak. Mint fentebb említettük, BigDecimalszámok ábrázolására szolgál, szigorú számítási pontossági követelményekkel. Jelenlegi formájában a számunk 10 számjegyből áll a tizedesvessző után. Ebből 7-et szeretnénk eldobni, és csak 3-at szeretnénk megtartani. Ennek megfelelően a 3-as szám mellett át kell lépnünk a kerekítési módot is. A BigDecimal összesen 8 kerekítési móddal rendelkezik. Az sok! De ha valóban finomítania kell a számítások pontosságát, akkor minden megvan, amire szüksége van. Tehát itt van a BigDecimal által kínált 8 kerekítési mód :
  1. ROUND_CEILING – felfelé kerekít

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN – nulla felé kerekít

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR – lefelé kerekít

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

  4. ROUND_HALF_UP — felfelé kerekít, ha a tizedesvessző utáni szám >= 0,5

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN – felfelé kerekít, ha a tizedesvessző utáni szám > 0,5

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN — a kerekítés a tizedesvesszőtől balra lévő számtól függ. Ha a bal oldali szám páros, a kerekítés lefelé történik. Ha a tizedesvesszőtől balra lévő szám páratlan, akkor a kerekítés felfelé történik.

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

    A tizedesjegytől balra lévő szám 2 (páros). A szám lefelé kerekítve. 0 tizedesjegyet akarunk, így az eredmény 2.

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

    A tizedesvesszőtől balra lévő szám 3 (páratlan). A szám felfelé kerekítve. 0 tizedesjegyet akarunk, így az eredmény 4.

  7. ROUND_UNNECCESSARY — Ez a mód akkor használatos, ha kerekítési módot kell átadnia egy metódusnak, de a számot nem kell kerekíteni. Ha megpróbál kerekíteni egy számot a ROUND_UNNECCESSARY móddal, akkor a rendszer egy Aritmetikai kivételt dob ​​fel.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP – kerekítés a nulláról.

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

Nagy számok összehasonlítása

Ez is fontos. Emlékszel, hogy az equals() metódust használjuk az objektumok összehasonlítására Java-ban. A megvalósítást vagy maga a nyelv biztosítja (a szabványos Java osztályokhoz), vagy a programozó írja felül. A BigDecimal objektumok esetében azonban nem javasolt az equals() metódus használata az összehasonlításhoz. Ennek az az oka, hogy a BigDecimal.equals() metódus csak akkor ad vissza igazat, ha a 2 szám értéke és skálája azonos: Hasonlítsuk össze az equals() metódus viselkedését a Double és BigDecimal osztályoknál:
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));

   }
}
Konzol kimenet:
true
false
Mint látható, a BigDecimal esetében az 1,5 és 1,50 számok egyenlőtlennek bizonyultak! Ez éppen az equals() metódus BigDecimal osztályban való megvalósításának sajátosságai miatt volt így . A két BigDecimal objektum pontosabb összehasonlításához jobb az összehasonlítás() metódus használata:
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));

   }
}
Konzol kimenet:
0
Az összehasonlítás() metódus 0-t adott vissza, ami azt jelenti, hogy 1,5 és 1,50 egyenlő. És ez az eredmény, amit vártunk! :) Ezzel a mai leckénk is véget ért. Itt az ideje, hogy visszatérjünk a feladatokhoz! :)
Hozzászólások
  • Népszerű
  • Új
  • Régi
Hozzászólás írásához be kell jelentkeznie
Ennek az oldalnak még nincsenek megjegyzései