倍精度について質問があります。float値がdoubleに渡されると、異なる結果が得られます。例えば
float f= 54.23f;
double d1 = f;
System.out.println(d1);
出力は54.22999954223633です。誰かがこの行動の背後にある理由を説明できますか?小数点以下の精度が14桁のデフォルトのdoubleのようなものですか。
倍精度について質問があります。float値がdoubleに渡されると、異なる結果が得られます。例えば
float f= 54.23f;
double d1 = f;
System.out.println(d1);
出力は54.22999954223633です。誰かがこの行動の背後にある理由を説明できますか?小数点以下の精度が14桁のデフォルトのdoubleのようなものですか。
Java 仕様では、値を同じ型の隣接する表現可能な値と区別するために必要な数の数字を印刷する必要があるため、同じ値が と に対して異なる方法で印刷されます (私の回答 here に従ってfloat
、定義の精度についてはリンクされたドキュメントを参照してください)。double
値を表すビットが少ないためfloat
、値が少ないため、間隔が広くなり、それらを区別するためにそれほど多くの桁数は必要ありません。値を に入力してdouble
出力する場合、Java 規則では、値を近くの値と区別できるように、より多くの桁を出力する必要がありdouble
ます。println
関数は、値が元々 から取得されたものであり、 に収まるほど多くの情報を含んでいないことを認識していませfloat
んdouble
。
54.23f
正確には 54.229999542236328125 (16 進数では 0x1.b1d70ap+5) です。このfloat
すぐ下とすぐ上の値は、54.2299957275390625 (0x1.b1d708p+5) と 54.23000335693359375 (0x1.b1d70cp+5) です。ご覧のとおり、「54.229999」と印刷すると、値が 54.229995… および 54.23… と区別されます。ただし、そのdouble
すぐ下とすぐ上の値54.23f
は、54.229999954223632101957264239899814128875732421875 と 54.229999954223633523042735760100185871124267578125 です。値を区別するには、「54.22999954223633」が必要です。
これは、floatが余分な小数を非表示にし、doubleがそれらを表示するためです。doubleは実際の数値を非常に正確に表し、より多くの桁を表示します。
これを試して:
System.out.println(f.doubleValue()); (もちろん最初にフロートにする必要があります)
ご覧のとおり、情報はそこにあり、丸められています。お役に立てれば
これは、内部表現によるものです。
浮動小数点数は通常、左から右に符号ビット、指数フィールド、仮数 (仮数) としてコンピューター データにパックされます。
これは、精度の問題と呼ばれます。
浮動小数点数がすべての実数を正確に表すことができないという事実、および浮動小数点演算が真の算術演算を正確に表すことができないという事実は、多くの驚くべき状況につながります。これは、コンピュータが数値を表現する一般的な有限精度に関連しています。
問題ありません。それが二重の仕組みです。あなたはそれを処理して気にする必要はありません。double の精度で十分です。あなたの数値と期待される結果との違いは、小数点以下の 14 桁目です。
任意の精度が必要な場合は、java.math.BigDecimal
クラスを使用してください。
または、それでも double を使用したい場合。次のようにします。
double d = 5.5451521841;
NumberFormat nf = new DecimalFormat("##.###");
System.out.println(nf.format(d));
ご不明な点がございましたら、お知らせください。
実際には、これは異なる視覚的表現または float / double から String への変換に関するものにすぎません。内部バイナリ表現を見てみましょう
float f = 0.23f;
double d = f;
System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));
System.out.println(Long.toBinaryString(Double.doubleToLongBits(d)));
出力
111110011010111000010100011111
11111111001101011100001010001111100000000000000000000000000000
f
に変換したことを意味しd1
、歪みはなく、有効桁数は同じです
double
さまざまな形式で数値をfloat
表します。
このため、一方の形式では完全に保存され、もう一方の形式では保存されない特定の数値を見つける必要があります。たまたま、に正しく収まるが、`doubleにfloat
は収まらないものを見つけました。exactly
この問題は、2つの異なるフォーマッターが使用されている場合にも発生する可能性があります。