1。はじめに
本「Efcactive Java」から単語を借りるために、フロートとダブルタイプの主な設計目標は、科学的なコンピューティングとエンジニアリングのコンピューティングです。彼らは、広い地域の数値範囲でより正確な高速近似を提供するように慎重に設計されたバイナリフローティングポイント操作を実行します。ただし、それらは完全に正確な結果を提供するものではなく、正確な結果が必要な状況では使用すべきではありません。ただし、商業的な計算では正確な結果が必要であり、現時点ではBigDecimalが役立ちます。
2。BigDecimalの紹介
Bigdecimalは、精度の整数非スケール値と32ビット整数スケールで構成されています。ゼロまたは正の場合、スケールは小数点後の数字数です。負の数の場合、数の非スケーリング値に10の負のパワーを掛けます。
3.テストコード
3.1コンストラクター(メインテストパラメータータイプは、ダブルと文字列を備えた2つの一般的なコンストラクターです)
コードコピーは次のとおりです。bigdecimaladouble = new bigdecimal(1.22);
system.out.println( "double value:" + adouble);
bigdecimal astring = new bigdecimal( "1.22");
system.out.println( "文字列値を持つコンストラクト:" +アストリング);
出力はどうなると思いますか?最初のものが1.22を出力するとは思わない場合は、答えを正しくおめでとうございます、出力の結果は次のとおりです。
コードを次のようにコピーします。ダブル値で構成:1.21999999999999999999993354647408996243029832839965820325
文字列値で構成:1.22
JDKの説明:
1.パラメータータイプダブルの構造方法の結果は予測不可能です。一部の人々は、JavaでNewbigdecimal(0.1)を書くことで作成された大きなdecimalは、0.1(スケールは1である非スケーリング値1)に正確に等しいと考えるかもしれませんが、実際には0.1000000000000000000000000000000000000555111512312578270218158340441015625。これは、0.1を二重として正確に表現できないためです(または、この場合、有限長のバイナリ10進数として表すことはできません)。このようにして、建設方法に渡された値は0.1に正確に等しくなりません(ただし、その値に等しくなります)。
2。一方、文字列構築方法は完全に予測可能です:Newbigdecimal( "0.1")への書き込みは、予想される0.1と正確に等しいBigdecimalを作成します。したがって、比較して、最初に文字列コンストラクターを使用することをお勧めします。
3.ダブルをBigDecimalのソースとして使用する必要がある場合、このコンストラクターは正確な変換を提供することに注意してください。次の操作と同じ結果は提供されません。最初にdouble.toString(double)メソッドを使用してから、BigDecimal(String)コンストラクターを使用してダブルを弦に変換します。結果を取得するには、静的値(double)メソッドを使用します。
3.2追加操作
コードコピーは次のとおりです。bigdecimala = new bigdecimal( "1.22");
System.out.println( "文字列値を持つコンストラクト:" + a);
BigDecimal B = new BigDecimal( "2.22");
A.Add(b);
system.out.println( "aplus b is:" + a);
出力すると考えるのは簡単です:
次のようにコードをコピーします:stringvalueで構成:1.22
プラスBは次のとおりです。3.44
しかし、実際にはプラスBは次のとおりです。1.22
4。ソースコード分析
4.1 Valueof(doubleval)メソッド
次のようにコードをコピーします。
//リマインダー:ゼロダブルは '0.0'を返しますので、私たちはfastpathすることができません
//定数ゼロを使用します。これは十分に重要かもしれません
//工場アプローチ、キャッシュ、またはいくつかのプライベートを正当化する
//定数、後で。
returnnew bigdecimal(double.tostring(val)); // JDK説明について3.1の3番目のポイントを参照してください
}
4.2追加(BigDecimal Augend)メソッド
public bigdecimal add(bigdecimal augend){long xs = this.intcompact; //整数数で表されるbigdecimal、たとえば、aは122 long ys = augend.intcompact; //上記と同じbiginteger fst =(this.intcompact!= flated)?null:this.intval; ?null:augend.intval; int rscale = this.scale; // 10進数は長いsdiff =(long)rscale -augend.scale; // 10進数の違いをif(sdiff!= 0){//最も小数点以下の小数を持つ小数点以下の場所は、(sdiff <0){int raise = raise = checkcale(-sdiff); rscale = augend.scale; if(xs ==膨張||(xs = longmultiplypowerten(xs、raise))== fst = bigmultiplypowerten(raise); } else {int raise = augend.checkscale(sdiff); if(ys ==膨張||(ys = longmultiplypowerten(ys、raise))== inflated)snd = augend.bigmultiplypowerten(raise); }} if(xs!= inflated && ys!= inflated){long sum = xs + ys; if((((sum ^ xs)&(sum ^ ys))> = 0l)//オーバーフローがあるかどうかを判断します。 return bigdecimal.valueof(sum、rcale); // bigdecimalの静的工場メソッドを使用して取得したbigdecimalインスタンスを返す} if(fst == null)fst = biginteger.valueof(xs); biginteger sum = fst.add(snd); return(fst.signum == snd.signum)?new bigdecimal(sum、inflated、rcale、0):new bigdecimal(sum、compactvalfor(sum)、rcale、0);上記は、追加のソースコードの分析にすぎません。減算、乗算、および分割は、実際に新しい大きなオブジェクトを返します。 BigintegerとBigdecimalはどちらも不変であるため、操作の各ステップを実行するときに新しいオブジェクトが生成されるため、A.Add(b)が生成されます。追加操作は実行されますが、Aは追加操作後の値を節約しません。正しい使用法はa = a.add(b)でなければなりません。
5。概要
(1)商業的計算では、BigDecimalを使用します。
(2)パラメーター型文字列を持つコンストラクターを使用してみてください。
(3)BigDecimalsは不変です。操作の各ステップを実行すると、新しいオブジェクトが生成されます。したがって、追加、減算、乗算、および分割を実行する場合、操作後に値を保存する必要があります。
(4)多くの場合、基礎となるJDKのいくつかの実装の詳細を無視する傾向があり、その結果エラーが発生するため、さらに注意を払う必要があります。
参照:クラスBigDecimal