2014-11-05 50 views
1

this question我寫了一個腳本來查找存儲一個值作爲總和的一部分,然後再返回可能產生的最大錯誤。爲什麼這個方程的最大誤差是4096 * Number.EPSILON?

我發現最大錯誤與Number.EPSILON:

maximumError/Number.EPSILON是一個不錯的輪數,8192 Math.log2(8192)是12.999999999999998,所以...... 13

有什麼關係這個舍入錯誤和Number.EPSILON?

爲什麼它是一個很好的因子2? 13「是什麼意思」是什麼?

UPDATE:腳本剛剛找到,其通過分割Number.EPSILON 3.637978807091713e-12的最大誤差爲16384 Math.log2(16384)〜= 14

+0

'Number.EPSILON'是'2^-52'。 '8192'是'2^13'。因此,通過代數,「maximumError」必須是「2^-39」。我不能告訴你更多關於'2^-39'「的含義是什麼,而沒有看到創建或使用'maximumError'的代碼,我想。 – apsillers 2014-11-05 17:49:53

+0

查看代碼的http://stackoverflow.com/questions/26761856/rounding-error-on-percent-of-total-and-back問題。問題是爲什麼這段代碼產生的最大錯誤是Number.EPSILON的一個因素。並且13是否通過說這是最大的位數錯誤或什麼? – 2014-11-05 17:52:47

回答

5

任何浮點值的值大於1 (或小於-1)除以Number.EPSILON必須爲爲整數。 (這並不一定值的真專門的範圍1-1內部。)

回想一下,浮點是位串(m,e)(尾數和指數),其中它們代表了數的值是m * 2^e的2元組。尾數設置值作爲一個位串,且指數移位的位到一定的功率在當前的ECMAScript 6草案的Number.EPSILON的定義是:

和最小的值1之間的差大於1的可表示爲一個數字值

我們採取的1000...0001尾數(1在尾數位串的最大和最小的數字)獲得ε和降級換檔尾數的二進制值1.000...0001負指數。摘要1,你有epsilon。注意,這是不最小的可能的浮點值,但它是精度提供給浮點值大於1的最小電平(或小於-1)*

至於爲什麼總是生成一個整數,這很容易解釋:對於大於1的數字,epsilon是最小可能的精度值。epsilon不可能不均勻地分配大於1的值,因爲這會表明數字有一些小於epsilon的小數部分,這在定義上是不可能的(因爲epsillon是>1數字的最小精度級別)。隨意在你的數字鍵盤上打鼓並將該數字除以Number.EPSILON - 你會看到結果是一個整數。

至於爲什麼結果總是2的冪,這似乎是因爲你的所有maximumError結果到目前爲止有一個尾數,這也是2個(可能是它們都具有的1尾數)的功率,所以它只是2的權力之間的劃分(因此結果也必須是2的冪)。

注意,所有產生這種情況下,a值的是那些具有在最低位一個1,所以它們的形式(2^n) + 1(和1本身)的:593365等。似乎在這裏有一些數學性質,其中乘法不恢復全部值,並且原始值爲100...000.1111111111...。它的數量很少,0.000000...000001。這個數字的格式表示爲1 * 2^-n,所以尾數永遠是1

您可能會發現感興趣的num.toString(2)的二進制表示:對於非常大或非常小的值,它清楚地顯示二進制尾數偏移零點,由* 2^e的指數位移造成。例如,請參見淋漓盡致出,比特移位尾數在Number.MAX_VALUE.toString(2)

1111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 

事實上,錯誤被生長的唯一原因是因爲在100...000.1111111111...尾隨1 S的數量被減少,由於固定的尺寸尾數。試想一下:

> var a = 9, b = 510; ((a/(a+b))*(a+b)).toString(2); 
"1000.1111111111111111111111111111111111111111111111111" 
> var a = 17, b = 4194; ((a/(a+b))*(a+b)).toString(2); 
"10000.111111111111111111111111111111111111111111111111" 

注意,這些字符串是完全一樣的長度,但小數點左邊是在第二種情況下1個數量級。這是因爲尾數只能保持一定數量的二進制數字。在邏輯上應該是無限數量的1 s將成爲儘可能多的1 s將適合浮點數。考慮十進制的類似情況,其中0.999... is actually equal to 1;因此,在二進制0.11111...等於1,但我們沒有空間來表示無限數字。

由於隨着小數點左邊的增長,拖尾數量減少,因此0.000...0001越來越接近小數點,因此誤差容限也會增加。


*:考慮一個簡單的尾數,如10001。如果你想使用尾數來儘可能小的值,你可以使用一個巨大的負指數產生一個值,如0.00000000000010001。但是,如果您需要保留大於1的值(與考慮Number.EPSILON的定義時一樣),則只能將其降至1.0001。最後的1可以走多遠的尾數大小,當領先1必須留在小數點左側。如果你只是試圖創造最小的價值,可以少於1,你可以將尾數更靠右移。

+0

這是一個很好的答案,爲我清除了一些東西。謝謝!你能說說是什麼讓這個操作有一個尾數嗎?那是因爲我操作中的「A」和「B」變量是整數? – 2014-11-05 19:19:49

+1

@AdamTerlson我更深入地研究了這個問題(浮點非常有趣!)並添加了更多信息。 – apsillers 2014-11-05 20:25:28

+0

我明白了。謝謝!確實超級有趣。 – 2014-11-05 21:34:54

相關問題