2011-07-06 4 views
0

JavaでKahan floating point summation algorithmを実装しました。私はそれをJavaでの組み込み浮動小数点加算とMathematicaでの無限精度加算と比較したいと思います。しかし、私が持っているデータセットは、数字がお互いに近いので、テストには向いていません。 (条件番号〜= 1)は、浮動小数点の合計をテストするための条件の悪いデータを生成します。

データセットにKahanを実行すると、組み込みの+とほとんど同じ結果になります。

大量のデータを生成する方法を提案しても、重大な丸め誤差が発生する可能性がありますか?

+0

"rouding errors"の部分で[this ibm site](http://www.ibm.com/developerworks/java/library/j-jtp0114/)を参照してください。基本的に、負の指数でバイナリとして表現できないいくつかの数値を生成する必要があります。例えば、0.5 = 2^-1であるが、0.1はそうではない。この[site](http://www.intel.com/standards/floatingpoint.pdf)もまた、それに関する良い理論を示しています。そして、丸め問題のためにJavaクラッシュを起こしたいと思っています。[このサイトを見てください](http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/)番号2.2250738585072012e-308、 – woliveirajr

答えて

1

しかし、私が持っているデータセットは、数字がお互いに近いので、テストには向いていません。

あなたはすでに問題が何かを知っているようですね。少ない数の精度の大半は、素朴な和で失われているように、乱暴に異なる大きさの

  • 番号、:あなたが望むだろういくつかのことがあります)=それに

    を取得します。

  • 異なる符号とほぼ等しい(または等しい)大きさの数字は、壊滅的なキャンセルが発生するようなものです。
  • 丸めの効果を高めるために、下位ビットをいくつか設定した数値。

あなたが開始するには、あなたが明確に効果を示すべき、いくつかの簡単な3項の合計を試みることができる:単純な和で評価

1.0 + 1.0e-20 - 1.0 

、これは0.0を与えます。明らかに間違っている。また、フォームの合計になります。bは単純に評価合計a0 + ... + anある

a0 + a1 + a2 + ... + an - b 

0

精度の高い数値のヒープが必要ですか?試してみてください:

0

私たちは数字のペアまたはシーケンスについて話していますか?

ペアの場合は、両方の数値に1を加え、繰り返しごとに1を3で割って、もう1つに3を掛けます。これらのペアの理論的な和を計算するのは簡単です。丸め誤差。 (分裂とほかのいくつかのいくつかのあなたの代わりに3の2を使用し、その後、除算エラーをしたくない場合。)実験によって

0

、私は次のパターンを見つけた:

public static void main(String[] args) { 
    System.out.println(1.0/3 - 0.01/3); 

    System.out.println(1.0/7 - 0.01/7); 

    System.out.println(1.0/9 - 0.001/9); 
} 

私はしました素数の近似的な負のべき乗を減算したものです(バイナリ形式で正確に表現すべきではありません)。そして、このような式が正しく評価されしかし、例があり、例えば、

System.out.println(1.0/9 - 0.01/9); 

のためにあなたは、たとえば、減数のパワーを反復して、適切な値による乗算は、整数の数を得ていない場合に停止することによって、このアプローチを自動化することができます。

System.out.println((1.0/9 - 0.001/9) * 9000); 
    if (1000 - (1.0/9 - 0.001/9) * 9000 > 1.0) 
     System.out.println("Found it!"); 
0

Scalacheckがあなたのためになるかもしれません。短いサンプルは次のとおりです。

cat DoubleSpecification.scala 
import org.scalacheck._ 

object DoubleSpecification extends Properties ("Doubles") { 
     /* 
      (a/1000 + b/1000) = (a+b)/1000 
      (a/x + b/x ) = (a+b)/x 
     */ 
     property ("distributive") = Prop.forAll { (a: Int, b: Int, c: Int) => 
      (c == 0 || a*1.0/c + b*1.0/c == (a+b) * 1.0/c)   } 
}  

object Runner { 
    def main (args: Array[String]) { 
     DoubleSpecification.check 
     println ("...done") 
    } 
} 

実行するには、scalaとschalacheck-jarが必要です。テストが失敗した場合

scalac -cp /opt/scala/lib/scalacheck.jar:. DoubleSpecification.scala 
scala -cp /opt/scala/lib/scalacheck.jar:. DoubleSpecification 
! Doubles.distributive: Falsified after 6 passed tests.      
> ARG_0: 28 (orig arg: 1030341) 
> ARG_1: 9 (orig arg: 2147483647) 
> ARG_2: 5 

Scalacheckがで、いくつかのランダムな値(ORIG引数)を受け取り、これらを単純化しようとします:私は(私はあなたのc-パスが変化すること、言うことはありません)バージョン2.8を使用しました簡単な例を見つけるために

関連する問題