Wak*_*eup 10 javascript precision epsilon
我想找到小于数组中某个值的值。我尝试使用Number.EPSILON,因为输入值不是一个确定值(例如1.5000000000001)。
我在测试中发现了一些奇怪的东西
>> (1.5 < 1.5 + Number.EPSILON)
<- true
>> (2.5 < 2.5 + Number.EPSILON)
<- false
Run Code Online (Sandbox Code Playgroud)
为什么是这样?测试环境是Chrome浏览器控制台。
虽然Number.EPSILON
可以精确地表示其自身,但这不能保证向其添加值(或进一步对其进行任何操作)将获得完美的精度。在这种情况下,1.5 + Number.EPSILON
得出的数字略高于1.5:
console.log(1.5 + Number.EPSILON);
Run Code Online (Sandbox Code Playgroud)
显然大于1.5。另一方面,将2.5加到Number.EPSILON
精确为2.5的结果–您希望获得的精度在加法过程中丢失了。
console.log(2.5 + Number.EPSILON);
Run Code Online (Sandbox Code Playgroud)
2.5 < 2.5
计算结果为false
,符合市场预期。
浮点数的精度有限。根据语言和体系结构,它们通常使用 32 位 ( float
) 或 64 位(double
,作为“双精度”)表示。尽管在像 JavaScript 这样的非类型语言中事情变得模糊,但这一切背后仍然有一个实际的机器,并且该机器必须执行浮点运算。
问题在于,由于精度有限,某些计算的结果无法准确表示。维基百科页面上有关浮点算术的一些示例对此进行了解释。
对于想要了解所有细节的人,通常会推荐有关“每个计算机科学家应该了解浮点运算”的文章。但说真的:并不是每个计算机科学家都需要知道这一切,而且我很确定世界上只有少数人真正读过整本书……
举一个过于暗示性的例子:假设你有 5 位数字来存储一个数字。当你添加像
10000.
+ 0.00001
--------------------
= 10000.
Run Code Online (Sandbox Code Playgroud)
该.00001
部分基本上会被“截断”,因为它不适合 5 位数字。
(这并不完全是这样的,但应该能传达这个想法)
Number.EPSILON
根据文档,的实际值约为2.22 * 10-16,并且是“1 与大于 1 的最小浮点数之间的差”。(这有时称为ULP,即“最后的单位”)。
因此,将此值添加到 1.0 将得到不同的数字。但将其与 2.5 相加并不会得到不同的数字,因为 2.5 与大于 2.5 的最小浮点数之间的差异比这个 epsilon还要大。因此,epsilon 被截断,如上.00001
例所示。
某些语言/库可能提供“ulp”函数,该函数返回给定值和下一个更大的可表示值之间的差异。例如,在 Java 中,您有
System.out.println(Math.ulp(1.0)); // Prints 2.220446049250313E-16
System.out.println(Math.ulp(2.5)); // Prints 4.440892098500626E-16
Run Code Online (Sandbox Code Playgroud)
第一个显然是存储在Number.EPSILON
. 第二个值是与 2.5 相加后应产生不同值的值。所以
2.5 < 2.5 + 4.4408E-16
将会是false
并且2.5 < 2.5 + 4.4409E-16
将会true
归档时间: |
|
查看次数: |
119 次 |
最近记录: |