Unvorhersagbarkeit des BigDecimal (double) -Konstruktors

9

Ich habe vor kurzem in einem Projekt mit Sonar angefangen, und ich habe eine PMD-Regel über den Konstruktor new BigDecimal(double val) gebrochen. Wenn ich die Java-Dokumentation lese, fand ich, dass BigDecimal (double val) etwas unvorhersehbar ist und dass ich new BigDecimal(String val) verwenden sollte, was vorhersehbar ist.

Hier ist, was javadoc für BigDecimal public BigDecimal(double val) sagt:

  

Übersetzt ein Double in ein BigDecimal, welches die genaue Dezimalzahl ist   Darstellung des binären Fließkommawertes des Doppelpunktes. Die Skala   des zurückgegebenen BigDecimal ist der kleinste Wert, so dass (10scale ×   val) ist eine ganze Zahl.

     

Anmerkungen:

     

Die Ergebnisse dieses Konstruktors können etwas unvorhersehbar sein. Ein   könnte annehmen, dass das Schreiben von new BigDecimal(0.1) in Java ein erstellt    BigDecimal , was exakt gleich 0,1 ist (ein unskalierter Wert von 1,   mit einer Skala von 1), aber es ist tatsächlich gleich   0.1000000000000000055511151231257827021181583404541015625. Dies liegt daran, dass 0.1 nicht genau als ein Doppel dargestellt werden kann   Materie als binärer Bruchteil beliebiger endlicher Länge). Also der Wert   das dem Konstruktor übergeben wird, ist nicht genau gleich   0,1, Erscheinungen ungeachtet.

     

Der String-Konstruktor hingegen ist perfekt vorhersehbar:   write new BigDecimal("0.1") erstellt ein BigDecimal was ist   genau gleich 0,1, wie man es erwarten würde. Daher ist es allgemein   empfohlen, dass stattdessen der String-Konstruktor verwendet wird   eins.

     

Wenn ein double als Quelle für BigDecimal verwendet werden muss, beachten Sie Folgendes   Dieser Konstruktor bietet eine genaue Konvertierung. es gibt nicht die   Das gleiche Ergebnis wie das Konvertieren des Double in einen String mit dem    Double.toString(double) Methode und dann mit der    BigDecimal(String) Konstruktor. Um dieses Ergebnis zu erhalten, verwenden Sie die statische    valueOf(double) Methode.

Warum existiert dieser Konstruktor wirklich? Ist%% genug für diese Angelegenheit? Wann sollte ich den new BigDecimal(String val) -Konstruktor verwenden?

    
gdfbarbosa 31.08.2012, 15:35
quelle

6 Antworten

6
  

Warum existiert dieser Konstruktor wirklich?

Er konvertiert den tatsächlich dargestellten Wert von double in ein BigDecimal. Der ganze Sinn von BigDecimal ist es, so viel Präzision wie möglich zu geben, und genau das macht dieser Konstruktor.

Wenn Sie den Wert, den Sie mit einer kleinen Rundung erhalten würden, verwenden möchten, verwenden Sie% /% %Vor%

druckt

%Vor%
  

Wann sollte ich den neuen Konstruktor BigDecimal (double val)

verwenden?

Wenn Sie wissen möchten, dass der Wert Double.toString(double) wirklich darstellt. Sie können Ihre eigene Rundung nach Bedarf anwenden.

Wenn Sie double verwenden, sollten Sie immer eine sinnvolle Rundung anwenden. Aber wenn Sie das getan haben, werden Sie möglicherweise BigDecimal nicht mehr benötigen. ;)

    
Peter Lawrey 31.08.2012, 15:40
quelle
2

Wenn Sie bereits mit einem double -Wert als Daten beginnen, haben Sie diese Präzisierung bereits verloren. Wenn Sie es nicht benötigen, müssen Sie es in String für BigDecimal konvertieren, um es zurück zu konvertieren.

Und vielleicht brauchen Sie auch manchmal diesen Wert.

    
SJuan76 31.08.2012 15:37
quelle
1

Sie würden den doppelten Konstruktor verwenden, wenn die Daten, mit denen Sie arbeiten möchten, bereits als doppelter Wert vorhanden sind. Das Konvertieren in eine Zeichenfolge vor dem Konvertieren in BigDecimal wäre in diesem Fall eine Verschwendung.

    
Philipp 31.08.2012 15:39
quelle
1

When should I use the new BigDecimal(double val) constructor?

Vorzugsweise - nirgendwo.

Wenn Sie bereit sind, mit BigDecimals zu spielen, bedeutet die Verwendung von Konstruktor mit Double, alle Vorteile der exakten Zahlenpräsentation zu verlieren.

Why does this constructor really exists?

Weil Sie manchmal nur Double haben, das Sie in BigDecimal übersetzen möchten. Sie zu zwingen, .toString() dazwischen zu verwenden, wäre einfach albern;)

    
dantuch 31.08.2012 15:39
quelle
0

Ich wollte etwas kommentieren, aber ich kann mir nicht vorstellen, wie man "Code" in einen Kommentar schreibt, also antworte ich:

double val = 0.1; // this is not 0.1, but an approximination as pointed out in other answers. BigDecimal biggy = new BigDecimal(val); // this variable conatains the "same" value as val does, however it is not 0.1, but as pointed out in other answers: 0.100000000000000005551115123

Also, in dem hier aufgelisteten Fall, wo Sie die volle Kontrolle über den Quellcode haben, sollten Sie das val als 'String val="0.1"'

schreiben

Der Konstruktor BigDecimal(double val) ist jedoch nützlich, wenn Sie binäre Doubles aus einer Datei lesen. Offensichtlich werden Sie in fast allen Fällen BigDecimals, die genau die gleichen sind wie die "Doppelgänger"

wollen     
Angel O'Sphere 26.11.2015 14:20
quelle
0

Unvorhersehbar? Ich stimme nicht zu.

%Vor%

Schlüssel zum Verständnis:

%Vor%

Wenn Sie wirklich "0.1" meinten, dann verwenden Sie den String-Konstruktor =). Wenn Sie aber bereits ein double haben, dann ist dieses Double nicht "0.1".

Der von Ihnen zitierte JavaDoc sagt:

  

Wenn ein Double als Quelle für ein BigDecimal verwendet werden muss, beachte das   Dieser Konstruktor bietet eine exakte Konvertierung;

Ich kann nicht sehen, wie eine genaue Umwandlung "unvorhersehbar" ist, und ich bin sehr dafür, das Wort "müssen" aus diesem Zitat zu entfernen.

Am Ende des Tages arbeiten beide Konstruktoren wie beabsichtigt. Wenn Sie String "0.1" haben, konvertiert BigDecimal (String) diesen Wert genau. Wenn Sie eine doppelte 0.1 haben, konvertieren Sie BigDecimal (double) diesen Wert genau.

    
Martin Andersson 24.06.2016 23:00
quelle

Tags und Links