JavaRush /Java-Blog /Random-DE /BigDecimal in Java

BigDecimal in Java

Veröffentlicht in der Gruppe Random-DE
Hallo! In der heutigen Vorlesung werden wir über große Zahlen sprechen. Nein, über die WIRKLICH GROSSEN. Zuvor haben wir mehr als einmal eine Tabelle mit Wertebereichen für primitive Datentypen gesehen. Es sieht aus wie das:
Primitiver Typ Größe im Speicher Wertebereich
Byte 8 Bit -128 bis 127
kurz 16 Bit bis -32768 bis 32767
verkohlen 16 Bit von 0 bis 65536
int 32 Bit von -2147483648 bis 2147483647
lang 64 Bit von -9223372036854775808 bis 9223372036854775807
schweben 32 Bit von (2 hoch -149) bis ((2-2 hoch -23)*2 hoch 127)
doppelt 64 Bit von (-2 hoch 63) bis ((2 hoch 63) - 1)
Boolescher Wert 8 (bei Verwendung in Arrays), 32 (bei Verwendung in Nicht-Arrays) richtig oder falsch
Wenn wir über Ganzzahlen sprechen, ist long der umfangreichste Datentyp , und wenn es um Gleitkommazahlen geht, ist double . Aber was ist, wenn die Zahl, die wir brauchen, so groß ist, dass sie nicht einmal in long passt ? Der Bereich möglicher Long-Werte ist recht groß, aber dennoch auf eine bestimmte Größe begrenzt – 64 Bit. Was können wir uns ausdenken, wenn unsere Very Large Number 100 Bit wiegt? Glücklicherweise müssen Sie nichts erfinden. In Java wurden für solche Fälle zwei spezielle Klassen erstellt – BigInteger (für ganze Zahlen) und BigDecimal (für Gleitkommazahlen). Was ist ihre Besonderheit? Erstens haben sie theoretisch keine maximale Größe. Theoretisch, denn es gibt keine Computer mit unendlichem Speicher. Und wenn Sie im Programm eine Zahl erstellen, die größer ist als der Speicher des Computers, funktioniert das Programm natürlich nicht. Aber solche Fälle sind unwahrscheinlich. Daher können wir sagen, dass die Größe der Zahlen praktisch unbegrenzt BigIntegerist . BigDecimalWofür werden diese Klassen verwendet? Erstens für Berechnungen mit extrem hohen Genauigkeitsanforderungen. Es gibt beispielsweise Programme, bei denen Menschenleben von der Genauigkeit der Berechnungen abhängen können (Software für Flugzeuge und Raketen oder für medizinische Geräte). Wenn also auch die 150. Dezimalstelle eine wichtige Rolle spielt, BigDecimalist sie die beste Wahl. Darüber hinaus werden diese Objekte häufig in der Finanzwelt eingesetzt, wo auch die Genauigkeit der Berechnungen bis hin zu kleinsten Werten äußerst wichtig ist. Wie arbeitet man mit Objekten BigIntegerund BigDecimalwas ist bei ihnen zu beachten? Objekte dieser Klassen werden wie folgt erstellt:
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);
   }
}
Die Übergabe eines Strings als Parameter ist nur einer der möglichen Konstruktoren. Here we use strings because our numbers exceed the maximum values long​​and double, and somehow we need to explain to the compiler exactly what number we want to get :) Just pass the number 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 to the constructor 1111111111111111111111111111111111111111111111111111111111111111111 will not work: Java will try to Passt die übergebene Zahl in einen der primitiven Datentypen ein, passt aber in keinen von ihnen. Daher ist die Verwendung einer Zeichenfolge zur Übergabe der gewünschten Zahl eine gute Option. Beide Klassen können automatisch numerische Werte aus übergebenen Strings extrahieren. Ein weiterer wichtiger Punkt, den Sie bei der Arbeit mit Klassen mit großen Zahlen beachten sollten, ist, dass ihre Objekte unveränderlich sind ( Immutable) . StringAm Beispiel einer Klasse und Wrapper-Klassen für Primitive (Integer, Long und andere) kennen Sie das Prinzip der Unveränderlichkeit bereits gut .
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);

   }
}
Konsolenausgabe:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Unsere Zahlen haben sich erwartungsgemäß nicht verändert. Damit die Additionsoperation erfolgreich ist, müssen Sie ein neues Objekt erstellen und ihm das Ergebnis der Addition zuweisen.
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);

   }
}
Konsolenausgabe:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Jetzt funktioniert alles wie es soll :) Ist Ihnen übrigens aufgefallen, wie ungewöhnlich die Additionsoperation aussieht?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
Dies ist ein weiterer wichtiger Punkt. Große Zahlenklassen verwenden in ihrer Operation nicht die Operatoren +-*/, sondern stellen stattdessen eine Reihe von Methoden bereit. Werfen wir einen Blick auf die wichtigsten (eine vollständige Liste der Methoden finden Sie wie immer in der Oracle-Dokumentation: hier und hier ).
  1. Methoden zur Durchführung arithmetischer Operationen: add() , subtract(), multiply(), divide(). Wird jeweils für Additions-, Subtraktions-, Multiplikations- und Divisionsoperationen verwendet.

  2. doubleValue(), intValue(), floatValue(), longValue()usw. – Wird zum Konvertieren einer großen Zahl in einen Java-Primitivtyp verwendet. Seien Sie vorsichtig bei der Verwendung und denken Sie an den Unterschied in der Kapazität!

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

    Konsolenausgabe:

    
    8198552921648689607
  3. min()und max()- ermöglichen es Ihnen, den minimalen und maximalen Wert zweier übergebener großer Zahlen zu ermitteln.
    Bitte beachten Sie: Methoden sind nicht statisch!

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

    Konsolenausgabe:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222

BigDecimal-Rundungssteuerung

Dieses Thema wird in einem separaten Abschnitt behandelt, da das Runden und Anpassen großer Zahlen keine so einfache Sache ist. BigDecimalMit können Sie die Anzahl der Dezimalstellen für eine Zahl festlegen setScale(). Beispielsweise möchten wir die Genauigkeit der Zahl 111,5555555555 auf drei Dezimalstellen festlegen. Wir werden jedoch nicht in der Lage sein, die Zahl 3 als Argument an die Methode zu übergeben setScale()und so unser Problem zu lösen. Wie oben erwähnt BigDecimalhandelt es sich hierbei um Zahlen für Berechnungen mit erhöhter Genauigkeit. In der aktuellen Form hat unsere Zahl 10 Dezimalstellen. Wir möchten 7 davon verwerfen und nur 3 übrig lassen. Daher müssen wir zusätzlich zur Zahl 3 den Rundungsmodus als Parameter übergeben . Insgesamt gibt es 8 Rundungsmodi BigDecimal. Ziemlich viel! Wenn Sie jedoch die Genauigkeit der Berechnungen im Programm wirklich verfeinern müssen, haben Sie alles, was Sie dafür benötigen. Hier sind also die 8 Rundungsmodi, die verfügbar sind in BigDecimal:
  1. ROUND_CEILING- Aufrunden

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN- Entladen entsorgen

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- Abrunden

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

  4. ROUND_HALF_UP— Aufrunden, wenn die Zahl nach dem Komma >= .5 ist

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— Aufrunden, wenn die Zahl nach dem Komma > .5 ist

    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
  6. ROUND_HALF_EVEN— Die Rundung hängt von der Zahl links vom Dezimalpunkt ab. Wenn die Zahl links gerade ist, wird nach unten gerundet. Ist die Zahl links vom Dezimalpunkt ungerade, wird sie aufgerundet.

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

    Die Zahl links vom Dezimalpunkt – 2 – ist gerade. Es wird abgerundet. Da wir 0 Dezimalstellen benötigen, ist das Ergebnis 2.

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

    Die Zahl links vom Dezimalpunkt – 3 – ist ungerade. Es wird nach oben gerundet. Da wir 0 Dezimalstellen benötigen, ist das Ergebnis 4.

  7. ROUND_UNNECCESSARY– Wird in Fällen verwendet, in denen der Rundungsmodus an eine Methode übergeben werden muss, die Zahl jedoch nicht gerundet werden muss. Wenn Sie versuchen, eine Zahl zu runden, während der ROUND_UNNECCESSARY-Modus festgelegt ist, wird eine ArithmeticException ausgelöst.

    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
  8. ROUND_UP- Aufrunden.

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

Vergleich großer Zahlen

Auch diese Frage ist wichtig. Sie erinnern sich bereits, dass die Methode zum Vergleichen von Objekten in Java verwendet wird equals(). Es wird entweder von der Sprache selbst bereitgestellt (im Fall der integrierten Klassen von Java) oder vom Programmierer überschrieben. Bei Klassenobjekten wird jedoch nicht empfohlen, BigDecimaldie Methode equals()zum Vergleich zu verwenden. Der Grund dafür ist, dass die BigDecimal.equals()Zwei-Zahlen-Methode nur dann „true“ zurückgibt , wenn die beiden Zahlen den gleichen Wert und die gleiche Skalierung habenequals() : Vergleichen wir das Verhalten der y- Doubleund y- Methoden 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));

   }
}
Konsolenausgabe:

true
false
Wie Sie sehen, erwiesen sich die Zahlen 1,5 und 1,50 im Fall von c BigDecimalals ungleich! Dies geschah genau aufgrund der Besonderheiten der Methode equals()in der Klasse BigDecimal. Für einen korrekteren Vergleich der beiden BigDecimalist es besser, die Methode zu verwenden compareTo():
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));

   }
}
Konsolenausgabe:

0
Die Methode compareTo()hat 0 zurückgegeben, was gleich 1,5 und 1,50 bedeutet. Das ist das Ergebnis, mit dem wir gerechnet haben! :) Damit ist unsere Lektion für heute abgeschlossen. Es ist Zeit, sich wieder den Aufgaben zuzuwenden! :) :)
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION