2012-11-20 61 views
7

java(加算/減算)で2つのdoubleの値を扱うときに、最大精度の損失がどの程度であるかを確立することは可能ですか?おそらく最悪のシナリオは、2つの数値を正確に表すことができず、演算が実行され、正確に表現できない値になる場合です。Java - 1回の二重加減算における精度の最大の損失

+0

精度の低下が問題になる場合は、doubleの代わりにBigDecimalを使用することをお勧めします。 –

+0

ええ、この質問の全体的なポイントは、損失がどのくらい大きいかを見ることです。 doubleは8バイト、BigDecimalは約40、多くのデータポイントを格納する必要があります – Bober02

+0

浮動小数点演算を多くすると、オブジェクトの代わりにプリミティブを使用することによるパフォーマンスの向上が重要になります。 – Cephalopod

答えて

5

Math.ulp(double)をご覧ください。 ulpdoubleは、次に高い値へのデルタです。例えば、数値に加算し、一方が他方のulpより小さい場合、加算は効果がないことを知っています。 2倍を2倍にすると、結果の最大誤差を得るためにulpsを掛けることができます。

+0

これは私が欲しかったものです – Bober02

7

すべての精度が失われる可能性があります。これは、例えば、結果が最大の表現可能な有限数よりも大きい場合に起こり得る。 POSITIVE_INFINITY(またはNEGATIVE_INFINITY)として格納されます。

アップデートに関しては、追加で発生する可能性があります。

double a = Double.MAX_VALUE; 
System.out.println(a); 
double b = a + a; 
System.out.println(b); 

結果:

1.7976931348623157E308 
Infinity 

はそれをオンラインで参照してください:一般的にideone

表現誤差の大きさは、あなたの数字の大きさを基準にしています。あなたは、たとえば、あなたの入力の実際の精度で出力以下のコードを見て可能性が

+0

上記の編集を参照してください - 私は主に追加を意味しました... – Bober02

0

input: 0.01000000000000000020816681711721685132943093776702880859375 
range: [0.0099999999999999984734433411404097569175064563751220703125 - 0.010000000000000001942890293094023945741355419158935546875] 
range size: 3.4694469519536141888238489627838134765625E-18 
input: 10000000000000000 
range: [9999999999999998 - 10000000000000002] 
range size: 4 
public static void main(String[] args) { 
    printRange(0.01); 
    printRange(10000000000000000d); 
} 

private static void printRange(double d) { 
    long dBits = Double.doubleToLongBits(d); 
    double dNext = Double.longBitsToDouble(dBits + 1); 
    double dPrevious = Double.longBitsToDouble(dBits + -1); 
    System.out.println("input: " + new BigDecimal(d)); 
    System.out.println("range: [" + new BigDecimal(dPrevious) + " - " + new BigDecimal(dNext) + "]"); 
    System.out.println("range size: " + new BigDecimal(dNext - dPrevious)); 
} 

をあなたはまだ、あなたの結果に損失を推定する必要があるだろう操作。そしてコーナーケース(Infinity、NaNなど)ではうまくいきません。

関連する問題