Legen Sie alle BigDecimal-Operationen, um eine gewisse Genauigkeit?
Mein Java-Programm ist zentriert rund um die hohe Präzision der Berechnungen, die müssen genau sein, mindestens 120 Dezimalstellen.
Folgerichtig, sind alle nicht-ganze zahlen werden dargestellt, indem BigDecimals in das Programm.
Ich natürlich angeben müssen, die Genauigkeit der Rundung für die BigDecimals, um zu vermeiden, unendliche Dezimalzahl Ausdrücken etc.
Derzeit finde ich es ein massives ärgernis zu haben, um anzugeben, die Genauigkeit bei jeder Instanziierung oder die mathematische operation einer BigDecimal.
Gibt es eine Möglichkeit, um eine 'Globale Genauigkeit' für alle BigDecimal-Berechnungen?
(Wie die Context.prec()
für die Dezimal - Modul in python)
Dank
Spezifikationen:
Java jre7 SE
Windows 7 (32)
Du musst angemeldet sein, um einen Kommentar abzugeben.
(Fast) Original
Nicht so einfach, aber du kannst ein
MathContext
und übergeben Sie es an alle IhreBigDecimal
Konstruktoren und die Methoden, die Durchführung von Operationen.Überarbeitet
Alternativ können Sie verlängern
BigDecimal
und überschreiben alle Operationen, die Sie verwenden möchten, indem Sie ihm die richtigenMathContext
, und mit der Rundung version vondivide
:divide
- Methode für die Klasse.divide
. Nun, ich denke, es wäre eine gute Idee, um Vorrang vor anderen Operationen verwenden, um sicherzustellen, dass Sie sind der Rückgabe eine Instanz der Klasse und nicht einer regelmäßigenBigDecimal
.MathContext
übergeben den Konstruktoren hat keinen Einfluss auf die späteren Operationen, nur die Konvertierung erfolgt im Konstruktor.number.divide(otherNumber);
syntax, da braucht mannumber
TypMyBigDecimal
und nichtBigDecimal
. Eine weitere option ist das einfach nur vergessen Unterklassen und schreiben Sie einestatic BigDecimal divide( BigDecimal a, BigDecimal b ){ a.divide(b,context);};
- Funktion und verwenden Sie es anstelle des einen zur Verfügung gestellt.Erstellen Sie eine
BigDecimalFactory
Klasse mit der statischen factory-Methoden passend zu allen Konstruktoren akzeptieren, dassMathContext
- außer, dass dieMathContext
Instanz innerhalb der Fabrik und statisch initialisiert beim Start. Hier ein fragment:MathContext
für die Konvertierung nur. Es ist nicht an das resultierendeBigDecimal
Objekt.BigDecimal
Instanzen erstellt mit der Fabrik ... es sei denn, Sie liefern denMathContext
als argument, um zu relevanten Vorgang.Nicht.
Müssen Sie erstellen Sie eine wrapper-Klasse, die eine
MathContext
als zusätzliches Attribut. Es müssen:verwenden Sie diese
mc
für jede mathematische operation, die andernfalls verwenden Sie die Standard-Semantik, understellen und bringe eine andere gewickelt Beispiel jedes mal, wenn Sie die verpackte operation liefert eine reguläre Instanz.
(Als Variante könnten Sie implementieren eine 'Globale'
MathContext
mit einem statischen, aber Sie werden immer noch auf wrappering, um sicherzustellen, dass diemc
verwendet wird.)(Erweiterung
BigDecimal
würde auch funktionieren, und das ist wohl sauberer als eine wrapper-Klasse.)Sie sagte dies in einem Kommentar:
(Design-Fragen können nur beantwortet werden endgültig durch das design-team. Jedoch ...)
Wie bei allen komplizierten utility-Klassen, die Gestaltung von BigDecimal ist ein Kompromiss, der ausgelegt ist, um die Anforderungen einer breiten Palette von Anwendungsfällen ab. Es ist auch ein Kompromiss zwischen den konkurrierenden meta-Anforderungen (Falsches Wort) von "Stärke" und "Einfachheit".
Was Sie haben, ist ein use-case, dass ist nicht besonders gut unterstützt. Aber ich vermute, dass, wenn es gut vertragen wurde (z.B. mit einem globalen
MathContext
alles kontrolliert oder eineMathContext
an jederBigDecimal
), dann das einführen würde alle Arten von anderen Komplexitäten, z.B. Umgang mit Operationen, wo es zwei oder mehr konkurrierende Kontext-Objekte zu berücksichtigen. Solche Probleme gelöst werden könnten ... aber Sie sind haftbar zu führen, um "überraschungen" für den Programmierer, und das ist nicht eine gute Sache.Der aktuelle Ansatz ist einfach und leicht zu verstehen, und wenn Sie etwas komplizierter, die Sie umsetzen können ... indem er explizit einen
MathContext
für die Vorgänge, die es erfordern.Könnten Sie eine Klasse erstellen, die erweitert
BigDecimal
und legt die Präzision automatisch für Sie. Dann müssen Sie nur verwenden Sie diese Klasse.Können Sie erstellen einen wrapper für die BigDecimals, die diesen job tun:
In diesem Fall werden Sie nicht haben, um überschreiben der Betrieb von BigDecimal (bei der Verlängerung der Fall ist), nur diejenigen, die Sie verwenden. Es gibt Ihnen die Kontrolle über alle Instanzen und nicht zwingen, zu Folgen BigDecimal-Vertrag.
Müssen Sie erstellen Sie Ihre eigenen wrapper-Klasse, die hat Ihre Standard-MathContext wie das vollständige Beispiel:
In diesem Beispiel habe ich die Bibliothek (https://projectlombok.org)
Test:
Können Sie die BigDecimal setScale Funktion!