精度を失うことなく、二重にフロートを変換します
-
06-09-2019 - |
質問
私は原始的なフロートを持っていると私はプリミティブなdoubleとして必要です。単純に倍増するフロートをキャストすることは私に奇妙な余分な精度を提供します。たとえばます:
float temp = 14009.35F;
System.out.println(Float.toString(temp)); // Prints 14009.35
System.out.println(Double.toString((double)temp)); // Prints 14009.349609375
しかし、代わりに文字列として鋳造、I出力フロートの場合は、ダブルなどの文字列を解析し、私は私が欲しいものを得る:
System.out.println(Double.toString(Double.parseDouble(Float.toString(temp))));
// Prints 14009.35
文字列と背面に移動するより良い方法はありますか?
解決
それはあなたがの実際の余分な精度を取得していることはありません - それは、フロートは正確にあなたがもともとを目指した数を表していなかったということです。ダブルはは正確に元のフロートを表すのです。 toString
がすでに存在していた「余分な」データを示している。
例えば(これらの数字は右ではないと、私は物事を作ってるんだ)あなたが持っていたと仮定します:
float f = 0.1F;
double d = f;
次にf
の値が正確に0.100000234523かもしれません。 d
はまったく同じ値を持つことになりますが、あなたはそれがより高精度に正確ですので、早けれ四捨五入しないという「信頼」される文字列に変換するとき、あなたがた「余分な数字」を参照してくださいよすでにそこが、あなたから隠されています。
あなたが戻って文字列に変換したとき、あなたはしたオリジナルのフロートよりも文字列値に近いdouble値で終わるている - が、のあなたが本当にいることを信じている場合には、の唯一の良いことです文字列値は、あなたが本当に欲しかったものです。
あなたはフロート/ダブル適切なタイプではなくBigDecimal
のここで使用するようになっていることを確認していますか?あなたは、正確な小数点以下の値(例えば、お金を)持っている番号を使用しようとしている場合は、BigDecimal
はIMOより適切なタイプです。
他のヒント
私はこの問題を把握しやすくバイナリ表現に変換見つけます。
float f = 0.27f;
double d2 = (double) f;
double d3 = 0.27d;
System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(f)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d2)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d3)));
あなたは最後まで0を追加することにより、フロートは、二重に拡張されて見ることができますが、0.27の二重の表現は、「より正確な」ので、問題であること。
111110100010100011110101110001
11111111010001010001111010111000100000000000000000000000000000
11111111010001010001111010111000010100011110101110000101001000
これは<のhref = "http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Float.html#toString(float)" のrel =」の契約によるものですnoreferrer "> Float.toString(float)
、一部に言うのます:
どのように多くの数字のために印刷されなければなりません 小数部分[...]?そこ 少なくとも一桁でなければなりません 小数部を表し、 超えているなど、多くの、のだけのように多くの、強いです> 一意に必要とされているように、の複数の数字 から引数の値を区別する float型の隣接する値。のこと xが正確であると仮定し、あります によって表される数学的な値 によって生成10進表現 有限ゼロでないため、この方法 引数F。そして、fはfloat型でなければなりません xに最も近い値。または、2つのfloatの場合 値は、F、xに等しく近いです そのうちの一つと少なくともでなければなりません の仮数の上位ビット F 0にする必要があります。
私は今日、この問題が発生しましたし、プロジェクトが本当に巨大であるため、BigDecimalのにリファクタリングを使用することができませんでした。しかし、私は使用して解決策を見つけた。
Float result = new Float(5623.23)
Double doubleResult = new FloatingDecimal(result.floatValue()).doubleValue()
そして、これは動作します。
result.doubleValue()を呼び出すことを返すことに注意してください5623.22998046875
しかしdoubleResult.doubleValue()を呼び出すと、
5623.23正しく返しますしかし、私は完全にわからないのであれば正解ます。
の代わりにBigDecimal
/ float
のdouble
を使用してください。二進浮動小数点(例えば、0.1
)として表すことができない数が多いです。だから、どちらか常に知ら精度や使用BigDecimal
に結果をラウンドする必要があります。
の詳細については、 http://en.wikipedia.org/wiki/Floating_pointするを参照してください。ます。
私は、次の解決策を見つけます:
public static Double getFloatAsDouble(Float fValue) {
return Double.valueOf(fValue.toString());
}
あなたが使用している場合は、のフロートとダブルの代わりにのフロートとダブルの次を使用する:
public static double getFloatAsDouble(float value) {
return Double.valueOf(Float.valueOf(value).toString()).doubleValue();
}
フロートは、性質上、不正確であり、常にきちんと丸め「問題」を持っています。精度が重要であるなら、あなたは小数やBigDecimalのを使用するようにアプリケーションをリファクタリング考えるかもしれません。
はい、山車は、プロセッサのサポートのための小数よりも計算高速です。ただし、高速または正確にしたいですか?
については、これは項目48の下に来る - 正確な値が必要な場合はジョシュアブロッホ効果的なJavaの第2版で、floatとdoubleを避けてください。この本は良いものと間違いなく一見の価値が詰め込まジャムです。
この仕事をしていますか?
float flt = 145.664454;
Double dbl = 0.0;
dbl += flt;