これは、Java のコードのスニペットです。
int i = 1234567890;
float f = i;
System.out.println(i - (int)f);
出力が 0 にならないのはなぜですか? 拡張を実行するため、データが失われることは想定されていません。次に、値を切り捨てます。よろしくお願いします
これは、Java のコードのスニペットです。
int i = 1234567890;
float f = i;
System.out.println(i - (int)f);
出力が 0 にならないのはなぜですか? 拡張を実行するため、データが失われることは想定されていません。次に、値を切り捨てます。よろしくお願いします
違いを見ます
int i = 1234567890;
float f = i;
System.out.println(i - f);
System.out.println((int)f);
System.out.println(f);
System.out.println(i-(int)f);
出力:
0.0
1234567936
1.23456794E9
-46
あなたの間違いはここにあります:
拡張を実行するため、データが失われることは想定されていません。
このステートメントは間違っています。拡大しても、データが失われないわけではありません。
Java仕様から:
拡大プリミティブ変換では、数値の全体的な大きさに関する情報が失われません。
int または long 値を float に、または long 値を double に変換すると、精度が失われる可能性があります。つまり、結果は値の最下位ビットの一部を失う可能性があります。この場合、結果の浮動小数点値は、IEEE 754 の最も近い値への丸めモード (§4.2.4) を使用して、整数値を正しく丸めたバージョンになります。
鉱山を強調します。
仕様には、大きさは失われないが、精度が失われる可能性があることが明確に記載されています。
拡大という言葉は、データ型の精度ではなく、その範囲を指します。float は int よりも範囲が広いため、幅が広くなっています。
整数
4 バイト、符号付き (2 の補数)。-2,147,483,648 ~ 2,147,483,647。
浮く
4 バイト、IEEE 754。1.40129846432481707e-45 から 3.40282346638528860e+38 (正または負) の範囲をカバーします。
ご覧のとおりfloat
、より広い範囲を持っています。ただし、浮動小数点数として正確に表現できない整数もあります。この表現エラーにより、結果が 0 とは異なります。f に格納される実際の値は 1234567936 です。
拡大すると精度が失われる可能性があります。anint
は 32 ビットの精度をfloat
持ち、a は 25 ビットの精度 (24 ビットの仮数と暗黙の最上位ビット) を持ちます。Javafloat
は64ビットよりも広いと考えていますlong
が、これはちょっとおかしいです
精度に 8 ビットの違いがあると、int
値が最も近いfloat
表現に丸められるため、エラーは最大約 +/-64 になる可能性があります。
int err = 0;
for (int i = Integer.MAX_VALUE; i > Integer.MAX_VALUE / 2; i--) {
int err2 = (int) (float) i - i;
if (Math.abs(err2) > err) {
System.out.println(i + ": " + err2);
err = Math.abs(err2);
}
}
版画
... deleted ...
2147483584: 63
2147483456: -64
これが真実である可能性があることを知ったら、あなたはショックを受けるでしょう:
(f==(f+1))==true
f
十分な大きさのフロートが与えられます...
int i = 1234567890;
float f = i;
System.out.println((int)f);
System.out.println(i);
System.out.println(i - (int)f);
出力は次のとおりです。
1234567936
1234567890
-46
違いを見ます。
integer float と比較すると値が大きくなります。