2011-07-06 57 views
0

我已經在Java中實現了Kahan floating point summation algorithm。我想將它與Java中內置的浮點加法和Mathematica中的無限精度加法進行比較。然而,我擁有的數據集不適合測試,因爲數據彼此接近。 (條件號〜= 1)生成用於測試浮點求和的病態數據

在我的數據集上運行Kahan可獲得與內置的+完全相同的結果。

任何人都可以建議如何生成大量的數據,可能會導致嚴重的四捨五入錯誤?

+0

在「路由錯誤」部分查看[this ibm site](http://www.ibm.com/developerworks/java/library/j-jtp0114/)。基本上,您需要生成一些不能用負指數二進制表示的數字。例如,0.5 = 2^-1,但不是0.1。 intel的這個[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

但是我的數據集不適合測試,因爲數字彼此接近。

這聽起來像你已經知道問題是什麼。得到它=)

有幾件事情,你會想:瘋狂不同幅度的

  • 編號,因此,大部分的小數值的精度是失去天真的總和。
  • 具有不同符號和接近相等(或相等)大小的數字,從而發生災難性取消。
  • 設置了一些低位比特的數字,以增加舍入的效果。

爲了讓您一開始,你可以嘗試一些簡單的三學期的款項,應清楚地顯示出效果:

1.0 + 1.0e-20 - 1.0 

與簡單相加評估,這會給0.0;顯然不正確。你也可以看看形式的總和:

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

哪裏b是天真地評估和a0 + ... + an

0

你想要一堆高精度的數字嗎?試試這個:

double[] nums = new double[SIZE]; 
for (int i = 0; i < SIZE; i++) 
    nums[i] = Math.rand(); 
0

我們在談論數字對還是序列?

如果成對,則從兩個數字開始,然後在每次迭代中除以3,將另一個乘以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。我使用的版本2.8(我不說了,你的C-路徑可能會有所不同):

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需要一些隨機值(原稿參數),並試圖簡化這些,如果測試失敗,爲了找到簡單的例子。