注意:JavaではDoubleからBigDecimalになります

Javaの世界規模の大規模な開発者ベースと簡単にアクセスできるオンラインAPIドキュメントの組み合わせにより、Java SEAPIの一般的に徹底的で正確なドキュメントが作成されました。希望するほど徹底的または正確ではない可能性のあるコーナーがまだありますが、APIドキュメントは、徹底性と正確性の両方の点で一般的にかなり優れています。

JavadocベースのAPIドキュメントは非常に便利になりましたが、開発者は非常に急いでいることが多く、自分の能力に自信を持っていることが多いため、最初にマニュアルを読まずに何かをしようとすることはほぼ避けられません。この傾向があるため、ドキュメントで特定のAPIをそのように(誤)使用しないように警告されているにもかかわらず、特定のAPIを誤用するとやけどを負うことがあります。これについては、Boolean.getBoolean(String)に関するブログ投稿で説明し、doubleを受け入れるBigDecimalのコンストラクターの使用に関連するこの投稿の同様の問題を強調しています。

一見すると、Java doubleを受け入れるBigDecimalコンストラクターは、すべての場合に元々指定された精度でそれを保持しているように見えるかもしれません。ただし、このコンストラクターのJavadocメッセージは、「このコンストラクターの結果は多少予測できない可能性がある」と明示的に警告しています。さらに、その理由を説明し(doubleは正確な精度を保持できず、BigDecimalコンストラクターに渡されると明らかになります)、代わりにStringをパラメーターとして受け入れる代替コンストラクターを使用することを提案します。ドキュメントでは、doubleまたはfloatをBigDecimalに変換するための推奨される方法としてBigDecimal.valueOf(double)を使用することも提案しています。

次のコードリストは、これらの原則といくつかの関連するアイデアを示すために使用されています。

DoubleToBigDecimal.java

import java.math.BigDecimal; import static java.lang.System.out; /** * Simple example of problems associated with using BigDecimal constructor * accepting a double. * * //marxsoftware.blogspot.com/ */ public class DoubleToBigDecimal { private final static String NEW_LINE = System.getProperty("line.separator"); public static void main(final String[] arguments) { // // Demonstrate BigDecimal from double // final double primitiveDouble = 0.1; final BigDecimal bdPrimDoubleCtor = new BigDecimal(primitiveDouble); final BigDecimal bdPrimDoubleValOf = BigDecimal.valueOf(primitiveDouble); final Double referenceDouble = Double.valueOf(0.1); final BigDecimal bdRefDoubleCtor = new BigDecimal(referenceDouble); final BigDecimal bdRefDoubleValOf = BigDecimal.valueOf(referenceDouble); out.println("Primitive Double: " + primitiveDouble); out.println("Reference Double: " + referenceDouble); out.println("Primitive BigDecimal/Double via Double Ctor: " + bdPrimDoubleCtor); out.println("Reference BigDecimal/Double via Double Ctor: " + bdRefDoubleCtor); out.println("Primitive BigDecimal/Double via ValueOf: " + bdPrimDoubleValOf); out.println("Reference BigDecimal/Double via ValueOf: " + bdRefDoubleValOf); out.println(NEW_LINE); // // Demonstrate BigDecimal from float // final float primitiveFloat = 0.1f; final BigDecimal bdPrimFloatCtor = new BigDecimal(primitiveFloat); final BigDecimal bdPrimFloatValOf = BigDecimal.valueOf(primitiveFloat); final Float referenceFloat = Float.valueOf(0.1f); final BigDecimal bdRefFloatCtor = new BigDecimal(referenceFloat); final BigDecimal bdRefFloatValOf = BigDecimal.valueOf(referenceFloat); out.println("Primitive Float: " + primitiveFloat); out.println("Reference Float: " + referenceFloat); out.println("Primitive BigDecimal/Float via Double Ctor: " + bdPrimFloatCtor); out.println("Reference BigDecimal/Float via Double Ctor: " + bdRefFloatCtor); out.println("Primitive BigDecimal/Float via ValueOf: " + bdPrimFloatValOf); out.println("Reference BigDecimal/Float via ValueOf: " + bdRefFloatValOf); out.println(NEW_LINE); // // More evidence of issues casting from float to double. // final double primitiveDoubleFromFloat = 0.1f; final Double referenceDoubleFromFloat = new Double(0.1f); final double primitiveDoubleFromFloatDoubleValue = new Float(0.1f).doubleValue(); out.println("Primitive Double from Float: " + primitiveDoubleFromFloat); out.println("Reference Double from Float: " + referenceDoubleFromFloat); out.println("Primitive Double from FloatDoubleValue: " + primitiveDoubleFromFloatDoubleValue); // // Using String to maintain precision from float to BigDecimal // final String floatString = String.valueOf(new Float(0.1f)); final BigDecimal bdFromFloatViaString = new BigDecimal(floatString); out.println("BigDecimal from Float via String.valueOf(): " + bdFromFloatViaString); } } 

上記のコードを実行した結果は、次の画面のスナップショットに示されています。

上記の出力が示すように、floatをdoubleにキャストする問題により、floatをBigDecimal.valueOf(double)メソッドに直接渡すときに必要な精度を維持できなくなります。文字列は、例に示されているように、またそれほど一般的ではない方法でフロートをダブルに変換する際に同様の方法で示されているように、これを実現するための仲介として使用できます。

GroovyでBigDecimalを暗黙的に多用すると、Groovyと動的型付けを使用するときにゲームが少し変わることに注意してください。これについては、今後のブログ投稿で触れる可能性があります。浮動小数点の問題の詳細(および「詳細」を強調します)については、すべてのコンピューター科学者が浮動小数点演算について知っておくべきことを参照してください。

このストーリー「注意:JavaでのDoubleからBigDecimal」は、もともとJavaWorldによって公開されました。