2

float を使ったサンプル プログラムを書いていたのですが、突然おかしなことが起こりました。私のプログラムからそのような行動に直面している理由について誰かが光を当てることができれば、本当に感謝しています。

package Programs;

public class FloatTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        float f1 = (float) 3.2;
        float f2 = (float) 6.5;
        if (f1 == 3.2) {
            System.out.println(f1 + " same");
        } else {
            System.out.println(f1 + " different");
        }
        if (f2 == 6.5) {
            System.out.println(f2 + " same");
        } else {
            System.out.println(f2 + " different");
        }
    }
}

出力:

3.2 different
6.5 same

f2 の値を変更していくつかのテストを行った後、f2 > 3.5 で予期しない結果が得られることに気付きました。ご意見をお待ちしております。

ありがとう

4

6 に答える 6

5

これについては、技術的な説明を試みます。これらの値は最終的にバイナリ形式で格納されるため、状況によっては精度が失われます。

6.5バイナリ値に変換できるため、精度を失うことはありません110.1

3.2.2ただし、 の 2 進数表現は無理数になるため、このようにきれいに変換することはできません。の線に沿ったものになります11.00110011..。これは、せいぜい、3.2逆に変換されたときに丸められるだけです。

誰かが私が言っていることを確認できたら、それは素晴らしいことです.これは、Javaがこれをどのように処理するかについての限られた知識に基づいている.

于 2013-09-13T19:15:50.737 に答える
2

キャストif (f1 == (float)3.2) {を使用すると機能します。

のようなリテラル3.2は double 型であり、float を double と比較しているため、そのようなことが発生します。

@JNLが指摘したように

この問題は、10 進値を 2 進数で正確に表すことができないために発生します。

于 2013-09-13T19:17:31.063 に答える
2

この問題を回避する方法はたくさんありますが、

この問題は、10 進値を 2 進数で正確に表すことができないために発生します。

  1. 許容値を持ち、差が許容値未満かどうかを確認します。
  2. 10/100/... を掛けて数値を比較します
  3. BigDecimalを調べます。

そして、これを確実に通過してください。

于 2013-09-13T19:10:16.407 に答える
2

:) ああ、IEEE754、およびフロートを使用した JVM の違い。簡単に言えば、6.5 は float 値の 6.5 と同じではありません。6.5 == 6.5f は動作しますが、自分が何をしているのかをよりよく理解できます! http://en.wikipedia.org/wiki/IEEE_floating_pointをお読みください。また、プラットフォーム間で IEEE754 の動作を強制するための「strictfp」キーワードにも注意してください。ここでは、丸め動作、優先順位、JVM の違いなど、考慮すべきことがたくさんあります。

無限に正確な答えを必要としない多くの種類の数学的計算に適した精度を持つ数値のバイナリ表現を操作しています。多くのエンジニアリングおよび金融システム、特に乗算や分数を含むシステムでは、これは受け入れられません。会計をリベースする必要があります (お金と小数を理解する金融クラスを使用する) (たとえば、お金のペニーでカウントする)、およびエンジニアリングのために、BigDecimal または特定の丸め動作、percision などを備えた関連クラスを使用する必要がある場合があります。 .

別の例を挙げると、1/3 + 1/3 + 1/3 の float 値は、1 に等しい場合とそうでない場合があります。データのデジタル表現を構成する 1 と 0 は正確に 1/3 ではないためです。私の特定のプラットフォーム (JVM 1.6 Windows 64 ビット) では 1.0 ですが、あなたのものではないかもしれません。

于 2013-09-13T19:10:56.970 に答える
1

正しくないように見えるかもしれませんが、実行すると

float f1 = (float) 3.2;

f1は実際には 3.2 と等しくありません。前述のように、この問題を回避するにはいくつかの方法があります。

于 2013-09-13T19:16:04.960 に答える