为什么 90 - .Machine$double.eps 不小于 90?

Why isn't 90 - .Machine$double.eps less than 90?

我对精度的理解肯定遗漏了一些东西,但我认为 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...

这种效应被称为失去意义 (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 变化,但相对精度在浮点数范围内几乎保持不变。