任何浮點值的值大於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
本身)的:5
,9
,33
,65
等。似乎在這裏有一些數學性質,其中乘法不恢復全部值,並且原始值爲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,你可以將尾數更靠右移。
'Number.EPSILON'是'2^-52'。 '8192'是'2^13'。因此,通過代數,「maximumError」必須是「2^-39」。我不能告訴你更多關於'2^-39'「的含義是什麼,而沒有看到創建或使用'maximumError'的代碼,我想。 – apsillers 2014-11-05 17:49:53
查看代碼的http://stackoverflow.com/questions/26761856/rounding-error-on-percent-of-total-and-back問題。問題是爲什麼這段代碼產生的最大錯誤是Number.EPSILON的一個因素。並且13是否通過說這是最大的位數錯誤或什麼? – 2014-11-05 17:52:47