在这里我对精度的了解一定会有所遗漏,但是我认为R可以代表步长为.Machine$double.eps
的网格上的数字,但是事实并非如此。实际上:
90 - .Machine$double.eps == 90
# [1] TRUE
这对我来说很奇怪,因为这两个数字(1)可以表示,而(2)不为零:
sprintf('%.16a', c(90, .Machine$double.eps))
# [1] "0x1.6800000000000000p+6" "0x1.0000000000000000p-52"
差异在数值上非零的第一位甚至更具启发性:
90 - 32*.Machine$double.eps < 90
# [1] FALSE
90 - 33*.Machine$double.eps < 90
# [1] TRUE
这种结果直接指向精度问题,但是我的理解在这里有一定的差距...
如果90 - .Machine$double.eps == 90
为何在我的计算机上没有double.eps
大?
这里的结果告诉我,实际上我应该有.Machine$double.eps == 2^5 * .Machine$double.eps
...
答案 0 :(得分:4)
这种效果称为重要性丢失(https://en.wikipedia.org/wiki/Loss_of_significance)。
90的有效数字会将.Machine$double.eps
移开。尝试
(90 - 46*.Machine$double.eps) == 90
这应该给您FALSE
。
machine.eps的定义:它是最低值eps
,1+eps
不是1
根据经验(假设浮点数以2为底):
这个eps
使得范围1 .. 2,
有所不同。
对于范围2 .. 4的精度为2*eps
等等。
x <- 3.8
(x + 2*.Machine$double.eps) == x
x <- 4
(x + 2*.Machine$double.eps) == x
# ...
x <- 63
(x + 32*.Machine$double.eps) == x
x <- 64
(x + 32*.Machine$double.eps) == x
浮点表示的绝对精度随x
的不同而变化,但是相对精度在浮点数范围内几乎是恒定的。