9

このメソッドは「true」を返します。なんで ?

public static boolean f() {
   double val = Double.MAX_VALUE/10;
   double save = val;
   for (int i = 1; i < 1000; i++) {
       val -= i;
   }
   return (val == save);
}
4

8 に答える 8

25

大きな値から非常に小さな値(1000未満)を減算しています。小さい値は大きい値よりもはるかに小さいため、理論結果に最も近い表現可能な値は元の値のままです。

基本的に、これは浮動小数点数の動作の結果です。

仮数に有効数字5桁と、0〜1000の範囲の指数のみを格納する10進浮動小数点型(簡単にするため)があるとします。

あなたの例は、10 999-1000と書くようなものです...有効数字5桁に丸めた場合、その結果がどうなるかを考えてください。はい、正確な結果は99999 ..... 9000(999桁)ですが、有効数字5桁の値しか表現できない場合、最も近い結果は10999になります。

于 2013-02-06T17:02:33.220 に答える
2

Double.MAX_VALUE / 10に設定valすると、ほぼ等しい値に設定され1.7976931348623158 * 10^307ます。そこから1000のような値を差し引くと、二重表現の精度が必要になりますが、これは不可能であるため、基本的にはval変更されません。

必要に応じて、BigDecimalの代わりに使用できますdouble

于 2013-02-06T17:04:34.480 に答える
2

Double.MAX_VALUE非常に大きいため、JVMはそれとの違いを認識しませんDouble.MAX_VALUE-1000

結果から「1.9958403095347198E292」よりも小さい数を引くと、Double.MAV_VALUEまだDouble.MAX_VALUEです。

System.out.println(  
            new BigDecimal(Double.MAX_VALUE).equals( new BigDecimal(  
                        Double.MAX_VALUE - 2.E291) )  
                ); 

System.out.println(  
           new BigDecimal(Double.MAX_VALUE).equals( new BigDecimal(  
                        Double.MAX_VALUE - 2.E292) )  
                       ); 

Ouptup:

true

false

于 2013-02-06T17:09:39.887 に答える
1

Double.MAX_VALUEは1または1000に比べて膨大な数です。Double.MAX_VALUE-1通常、はに等しくなりDouble.MAX_VALUEます。したがって、1または1000をに減算しても、コードは大まかに何もしませんDouble.MAX_VALUE/10。常に覚えておいてください:

  1. doublesまたはfloatsは実数の単なる近似であり、実数間で均等に分散されていない単なる有理数です。
  2. double近くにないsまたはsの間で非常に注意深く算術演算子を使用する必要floatがあります(このような他の多くのルールがあります...)
  3. 一般に、doublesを使用しないでください。またはfloat、任意精度が必要な場合は、
于 2013-02-06T17:08:18.550 に答える
1

doubleには、試行している計算を実行するのに十分な精度がありません。したがって、結果は初期値と同じになります。

==オペレーターとは何の関係もありません。

于 2013-02-06T17:02:50.797 に答える
1

valは大きな数であり、そこから減算1(または1000)すると、結果を値として正しく表現できませんdouble。無制限の数を表すために限られた数のビットしかないため、この数の表現はx同じx-1です。double

于 2013-02-06T17:04:46.000 に答える
0

浮動小数点計算の結果は、正確な答えに最も近い表現可能な値です。このプログラム:

public class Test {
  public static void main(String[] args) throws Exception {
    double val = Double.MAX_VALUE/10;
    System.out.println(val);
    System.out.println(Math.nextAfter(val, 0));
  }
}

プリント:

1.7976931348623158E307
1.7976931348623155E307

これらの数値の最初は、元の値です。2番目はそれよりも小さい最大のダブルです。

1.7976931348623158E307から1000を引くと、正確な答えはこれら2つの数値の間にありますが、1.7976931348623155E307よりも1.7976931348623158E307に非常に近いため、結果は1.7976931348623155E307に丸められ、valは変更されません。

于 2013-02-07T06:54:12.277 に答える
0

double浮動小数点数値型であり、数値を概算する方法であるためです。浮動小数点表現は数値をエンコードするため、通常よりもはるかに大きい数値または小さい数値を格納できます。ただし、指定されたスペースですべての数値を表すことができるわけではないため、複数の数値は同じ浮動小数点値に丸められます。

簡単な例として、通常は-10から10しか格納できない小さなスペースに、-1000から1000の範囲の値を格納できるようにしたい場合があります。したがって、すべての値を1000の位に丸めることができます。 -1000はとしてエンコードされ-10、-900はとしてエンコードされ-9、1000はとしてエンコードされ10ます。しかし、-999を保存したい場合はどうなりますか?エンコードできる最も近い値は-1000であるため、-999を-1000と同じ値としてエンコードする必要があります-10

実際には、浮動小数点スキームは上記の例よりもはるかに複雑ですが、概念は似ています。数値の浮動小数点表現は、可能なすべての数値の一部しか表現できないため、スキームの一部として表現できない数値がある場合は、最も近い表現可能な値に丸める必要があります。

コードでは、1000以内のすべての値がDouble.MAX_VALUE / 10自動的にに丸められます。Double.MAX_VALUE / 10これが、コンピューターが考える理由(Double.MAX_VALUE / 10) - 1000 == Double.MAX_VALUE / 10です。

于 2013-02-06T17:17:13.657 に答える