gpt4 book ai didi

javascript - 为什么该方程式的最大误差为4096 * Number.EPSILON?

转载 作者:行者123 更新时间:2023-11-30 08:40:41 27 4
gpt4 key购买 nike

this question中,我编写了一个脚本,以查找将值存储为总和的一部分然后再次返回时可能出现的最大错误。

我发现最大错误与Number.EPSILON有关:

maximumError / Number.EPSILON是一个很好的整数,为8192。
Math.log2(8192)是12.999999999999998,所以... 13。

此舍入错误与Number.EPSILON之间有什么关系?

为什么它是2的好因子? 13个“平均值”是什么?

更新:脚本刚刚发现最大错误3.637978807091713e-12除以Number.EPSILON是16384。Math.log2(16384)〜= 14。

最佳答案

任何大于1(或小于-1)的浮点值除以Number.EPSILON的值都必须是整数。 (仅在1-1范围内的值不一定是正确的。)

回想一下,浮点数是位字符串(m,e)(尾数和指数)的2元组,其中它们表示的数字的值是m * 2^e。尾数将值设置为位串,并且指数将这些位移位为一定的幂。在当前的ECMAScript 6草案中,Number.EPSILON的定义为:


  1与可表示为Number值的大于1的最小值之间的差


我们通过获取尾数1000...0001(尾数位串的最大和最小位数为1)和将尾数向下移动至二进制值1.000...0001的负指数来得出epsilon。减去1,您将得到epsilon。请注意,这不是可能的最小浮点值,而是对于大于1(或小于-1)的浮点值可用的最小精度级别。*

至于为什么总是产生整数,这很容易解释:epsilon是大于1的数字的最小可能精度值。epsilon不可能不均匀地划分大于1的值,因为这表明数字有一些小于epsilon的小数部分,这绝对是不可能的(因为epsillon是>1数的最小精度级别)。随意敲击数字键盘,然后将该数字除以Number.EPSILON-您会看到结果是整数。

至于为什么结果始终是2的幂的原因,这似乎是因为到目前为止,您所有的maximumError结果都具有2的幂的尾数(可能它们都具有1的尾数),所以只是2的幂之间的除法(因此结果也必须是2的幂)。

请注意,所有产生这种情况的a值都是最低位具有1的那些值,因此它们的形式为(2^n) + 1(以及1本身):593365等。这里似乎存在一些数学属性,其中乘法不能恢复完整值,并且原始的100...001值变为100...000.1111111111...0.000000...000001很小。该数字的格式表示为1 * 2^-n,因此尾数始终为1

您可能会发现感兴趣的以num.toString(2)表示的二进制表示形式:对于非常大或非常小的值,它清楚地显示了由于* 2 ^ e的指数位移引起的二进制尾数偏移为零。例如,请参见Number.MAX_VALUE.toString(2)中已最大化的,移位的尾数:

1111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000


实际上,误差增加的唯一原因是由于尾数的固定大小,导致 1中尾随 100...000.1111111111...的数量正在减少。考虑:

> 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。考虑十进制的类似情况,其中 0.999... is actually equal to 1;因此,在二进制中, 0.11111...等于 1,但是我们没有空间来表示无限数字。

由于尾数的位数随着小数点左边的增加而减少,因此误差范围也增加,因为 0.000...0001越来越接近小数点。



*:考虑一个简单的尾数,例如 10001。如果要使用该尾数使值尽可能小,则可以使用极大的负指数来产生类似 0.00000000000010001的值。但是,如果需要保持该值大于 1(就像在考虑 Number.EPSILON的定义时一样),则只能将其向下移动到 1.0001。当最后一个 1必须保留在小数点左边时,最后的 1可以走多远取决于尾数的大小。如果您只是想创建最小值,并且可以小于1,则可以将尾数向右移动得更远。

关于javascript - 为什么该方程式的最大误差为4096 * Number.EPSILON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26763595/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com