From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+Seit dem JDK 1.1 gibt es das Paket java.math
+mit den beiden Klassen BigInteger
+und BigDecimal.
+Beide implementieren beliebig große bzw. beliebig genaue Zahlen
+und stellen Methoden zur Durchführung arithmetischer Berechnungen
+zur Verfügung. Während BigInteger
+beliebig große Ganzzahlen implementiert, dient BigDecimal
+zur Darstellung sehr großer Fließkommazahlen. Objekte
+beider Klassen sind immutable, d.h. sie können nach der
+Instanzierung nicht mehr verändert werden.
+
+
+
+
+
+Die einfachste Art, ein BigInteger-Objekt
+zu konstruieren, besteht darin, eine String-Repräsentation der
+darzustellenden Zahl an den Konstruktor zu übergeben. Das kann
+wahlweise mit oder ohne Angabe des Zahlensystems geschehen:
+
+
+Wird das Zahlensystem nicht angegeben, erwartet der Konstruktor eine
+Zahl zur Basis 10. Der übergebene String darf eine beliebig lange
+Folge von Ziffern sein. An erster Stelle kann ein Minuszeichen stehen,
+um eine negative Zahl anzuzeigen.
+
+
+Die Arithmetik auf BigInteger-Zahlen
+erfolgt durch Aufruf ihrer arithmetischen Methoden und Übergabe
+der erforderlichen Argumente, die meist ebenfalls vom Typ BigInteger
+sind. Der Methodenaufruf verändert dabei nicht den Wert des Objekts,
+sondern gibt das Ergebnis als neue BigInteger-Zahl
+an den Aufrufer zurück. Wichtige arithmetische Methoden sind:
+
+
+
+
+Sie berechnen die Summe, Differenz, Produkt, Quotient, Restwert und
+Potenz zweier BigInteger-Zahlen.
+Neben den Grundrechenarten gibt es weitere Funktionen:
+
+
+
+Sie stellen den absoluten Betrag zur Verfügung, multiplizieren
+mit -1, liefern das Vorzeichen und ermitteln den größten
+gemeinsamen Teiler zweier Zahlen. min
+und max
+liefern den kleineren bzw. größeren Wert aus aktueller
+und als Argument übergebener Zahl. Daneben gibt es logische und
+bitweise Operationen, die denen der primitiven ganzzahligen Typen
+entsprechen.
+
+
+Zum Vergleich zweier BigInteger-Zahlen
+kann compareTo
+und equals
+verwendet werden, die Konvertierung in einen String wird mit toString
+erledigt:
+
+
+Die Arbeitsweise dieser Methoden entspricht der in der Klasse Object
+und dem Interface Comparable
+definierten und kann in Abschnitt 8.1.2
+und Abschnitt 9.2 nachgelesen
+werden. Schließlich gibt es noch einige Methoden, um BigInteger-Objekte
+in primitive Typen zu verwandeln:
+
+
+Die Umwandlung folgt den in Abschnitt 4.6
+beschriebenen Regeln für einschränkende Konvertierungen.
+
+
+Als abschließendes Beispiel wollen wir uns ein kleines Programm
+ansehen, das die Fakultäten der Zahlen 30 bis 40 berechnet:
+
+
+
+
+
+
+ Titel
+ Inhalt
+ Suchen
+ Index
+ DOC
+ Handbuch der Java-Programmierung, 5. Auflage
+
+ <<
+ <
+ >
+ >>
+ API
+ Kapitel 17 - Utility-Klassen II
+
+
+
+
+
+17.3 Die Klassen BigInteger und BigDecimal
+
+
+
+
+17.3.1 Die Klasse BigInteger
+
+
+
+
+
+
+
+
+
+
+public BigInteger(String val)
+
+public BigInteger(String val, int radix)
+
+
+
+java.math.BigInteger
+
+
+
+
+
+
+
+
+
+public BigInteger add(BigInteger val)
+public BigInteger subtract(BigInteger val)
+public BigInteger multiply(BigInteger val)
+public BigInteger divide(BigInteger val)
+public BigInteger remainder(BigInteger val)
+public BigInteger pow(int exponent)
+
+
+
+java.math.BigInteger
+
+
+
+
+
+
+
+
+
+public BigInteger abs()
+public BigInteger negate()
+public int signum()
+public BigInteger gcd(BigInteger val)
+
+public BigInteger min(BigInteger val)
+public BigInteger max(BigInteger val)
+
+
+
+java.math.BigInteger
+
+
+
+
+
+
+
+
+
+public int compareTo(BigInteger val)
+public boolean equals(Object x)
+
+public String toString()
+
+
+
+java.math.BigInteger
+
+
+
+
+
+
+
+
+
+public int intValue()
+public long longValue()
+public float floatValue()
+public double doubleValue()
+
+
+
+java.math.BigInteger
+
+
+
+Listing 17.5: Anwendung der Klasse BigInteger
+
+
+
+
+
+001 /* Listing1705.java */
+002
+003 import java.math.*;
+004
+005 public class Listing1705
+006 {
+007 public static void printFaculty(int n)
+008 {
+009 BigInteger bi = new BigInteger("1");
+010 for (int i = 2; i <= n; ++i) {
+011 bi = bi.multiply(new BigInteger("" + i));
+012 }
+013 System.out.println(n + "! is " + bi.toString());
+014 }
+015
+016 public static void main(String[] args)
+017 {
+018 for (int i = 30; i <= 40; ++i) {
+019 printFaculty(i);
+020 }
+021 }
+022 }
+
+
+Listing1705.java
+
+Die Ausgabe des Programms ist:
+
+
+30! is 265252859812191058636308480000000
+31! is 8222838654177922817725562880000000
+32! is 263130836933693530167218012160000000
+33! is 8683317618811886495518194401280000000
+34! is 295232799039604140847618609643520000000
+35! is 10333147966386144929666651337523200000000
+36! is 371993326789901217467999448150835200000000
+37! is 13763753091226345046315979581580902400000000
+38! is 523022617466601111760007224100074291200000000
+39! is 20397882081197443358640281739902897356800000000
+40! is 815915283247897734345611269596115894272000000000
+
+
+
+
+
+
+
+Die Klasse BigDecimal +kann beliebig genaue Fließkommazahlen darstellen. Sie bestehen +aus einer Ziffernfolge (die als Objekt vom Typ BigInteger +gespeichert ist) und einer Skalierung, die als nicht-negative +Ganzzahl gespeichert wird. Die Skalierung bestimmt die Anzahl der +Nachkommastellen. Der Wert der Zahl ergibt sich aus der Formel Unskalierter +Wert / (10 Skalierung). + +
+Die Instanzierung eines BigDecimal-Objekts +kann analog zur Klasse BigInteger +durch Übergabe eines Strings an den Konstruktor erfolgen. Dabei +ist neben dem ganzzahligen Teil zusätzlich ein Dezimalpunkt und +ein Gleitkommateil erlaubt. Die Anzahl der Nachkommastellen bestimmt +die Skalierung. Alternativ kann das Objekt auch aus einem BigInteger +oder einem double +konstruiert werden: +
+
+
++public BigDecimal(BigInteger val) +public BigDecimal(double val) +public BigDecimal(String val) ++ + |
++java.math.BigDecimal | +
+BigDecimal +stellt elementare arithmetischen Funktionen zur Verfügung: +
+
+
++public BigDecimal add(BigDecimal val) +public BigDecimal subtract(BigDecimal val) +public BigDecimal multiply(BigDecimal val) +public BigDecimal divide(BigDecimal val, int roundingMode) + +public BigDecimal abs() +public BigDecimal negate() +public int signum() + +public BigDecimal min(BigDecimal val) +public BigDecimal max(BigDecimal val) ++ + |
++java.math.BigDecimal | +
+Ihr Verhalten entspricht weitgehend dem bei BigInteger +beschriebenen. Eine Ausnahme bildet die Methode divide, +denn sie benötigt zusätzlich eine Konstante, die die Art +der Rundung (falls erforderlich) bestimmt: +
+Auch die Konvertierungs- und Vergleichsmethoden entsprechen denen +der Klasse BigInteger: +
+
+
++public int compareTo(BigDecimal val) +public boolean equals(Object x) + +public String toString() + +public int intValue() +public long longValue() +public float floatValue() +public double doubleValue() ++ + |
++java.math.BigDecimal | +
+Mit Hilfe der Methoden scale +und setScale +kann die Skalierung abgefragt bzw. ein neues Objekt mit geänderter +Skalierung erzeugt werden: +
+
+
++public int scale() + +public BigDecimal setScale(int scale) +public BigDecimal setScale(int scale, int roundingMode) ++ + |
++java.math.BigDecimal | +
+Das Ändern der Skalierung läßt den numerischen Wert +des Objekts intakt und verändert lediglich die Anzahl der darstellbaren +Dezimalstellen. Soll diese verkleinert werden, muss die zweite Variante +von setScale +verwendet und eine passende Rundungskonstante übergeben werden. +Soll die Anzahl der Dezimalstellen vergrößert werden, kann +die erste Variante verwendet werden. + +
+Zusätzlich gibt es zwei Methoden, mit denen der Dezimalpunkt +um eine bestimmte Anzahl Stellen nach links oder rechts verschoben +werden kann, also eine Multiplikation bzw. Division mit einer Zehnerpotenz +ausgeführt wird: +
+
+
++public BigDecimal movePointLeft(int n) +public BigDecimal movePointRight(int n) ++ + |
++java.math.BigDecimal | +
+Zum Abschluss wollen wir uns ein Beispielprogramm ansehen, das die +Quadratwurzel der Zahl 2 in (theoretisch) beliebiger Genauigkeit errechnen +kann: + + +
+
+
+
+001 /* Listing1706.java */
+002
+003 import java.math.*;
+004
+005 public class Listing1706
+006 {
+007 public static final BigDecimal ZERO = new BigDecimal("0");
+008 public static final BigDecimal ONE = new BigDecimal("1");
+009 public static final BigDecimal TWO = new BigDecimal("2");
+010
+011 public static BigDecimal sqrt(BigDecimal x, int digits)
+012 {
+013 BigDecimal zero = ZERO.setScale(digits + 10);
+014 BigDecimal one = ONE.setScale(digits + 10);
+015 BigDecimal two = TWO.setScale(digits + 10);
+016 BigDecimal maxerr = one.movePointLeft(digits);
+017 BigDecimal lower = zero;
+018 BigDecimal upper = x.compareTo(one) <= 0 ? one : x;
+019 BigDecimal mid;
+020 while (true) {
+021 mid = lower.add(upper).divide(two, BigDecimal.ROUND_HALF_UP);
+022 BigDecimal sqr = mid.multiply(mid);
+023 BigDecimal error = x.subtract(sqr).abs();
+024 if (error.compareTo(maxerr) <= 0) {
+025 break;
+026 }
+027 if (sqr.compareTo(x) < 0) {
+028 lower = mid;
+029 } else {
+030 upper = mid;
+031 }
+032 }
+033 return mid;
+034 }
+035
+036 public static void main(String[] args)
+037 {
+038 BigDecimal sqrtTwo = sqrt(TWO, 100);
+039 BigDecimal apxTwo = sqrtTwo.multiply(sqrtTwo);
+040 System.out.println("sqrt(2): " + sqrtTwo.toString());
+041 System.out.println("check : " + apxTwo.toString());
+042 }
+043 }
+
+ |
++Listing1706.java | +
+Das Programm arbeitet mit einer Intervallschachtelung. Dazu werden +zunächst passende Unter- und Obergrenzen gesucht, so dass das +Quadrat der Untergrenze auf jeden Fall kleiner gleich und das Quadrat +der Obergrenze größer oder gleich der gesuchten Zahl ist. +Nun wird der Wert genau in der Mitte zwischen beiden Punkten quadriert +und mit dem gesuchten Ergebnis verglichen. Ist er größer, +wird die Mitte als neue Obergrenze verwendet, andernfalls als neue +Untergrenze. Diese Iteration wird solange fortgesetzt, bis der Fehler +kleiner als der maximal erlaubte ist. +
+
![]() |
+
+
+ +Das Beispielprogramm berechnet das Ergebnis auf etwa 100 Stellen nach +dem Komma. Dieser Wert kann prinzipiell beliebig vergrößert +werden. Zu bedenken ist allerdings, dass dadurch die Laufzeit überproportional +ansteigt. Zwar bleibt die Intervallschachtelung an sich performant, +aber durch die größere Anzahl an zu verarbeitenden Dezimalstellen +benötigt jeder einzelne Aufruf einer arithmetischen Methode mehr +Rechenzeit. Zudem erfordert die höhere Genauigkeit insgesamt +mehr Iterationen, so dass insgesamt das Laufzeitverhalten wohl quadratisch +mit der Genauigkeitsanforderung wachsen dürfte. |
+
+
|
+![]() |
+
| Titel + | Inhalt + | Suchen + | Index + | DOC + | Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 + |
| << + | < + | > + | >> + | API + | © 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de + |