因此,我只是在手动计算R中e
的值,然后发现有些东西令我感到不安。
使用R的e
命令获取exp()
的值...
exp(1)
#[1] 2.718282
现在,我将尝试使用x = 10000
x <- 10000
y <- (1 + (1 / x)) ^ x
y
#[1] 2.718146
不太清楚,但我们将尝试使用x = 100000
x <- 100000
y <- (1 + (1 / x)) ^ x
y
#[1] 2.718268
温暖,但还是有点...
x <- 1000000
y <- (1 + (1 / x)) ^ x
y
#[1] 2.71828
现在,让我们尝试一个巨大的
x <- 5000000000000000
y <- (1 + (1 / x)) ^ x
y
#[1] 3.035035
嗯,那是不对的。这里发生了什么?我是否溢出数据类型,而需要使用某个包?如果是这样,当您溢出数据类型时是否没有警告?
答案 0 :(得分:7)
您的机器精度存在问题。 (1 / x) < 2.22e-16
刚好为1 + (1 / x)
。1在有限精度数值计算中,数学极限被打破。问题中的最后一个x
已经是5e+15
,非常接近这个边缘。尝试x <- x * 10
,您的y
将是1
。
这既不是“上溢”也不是“下溢”,因为表示1e-308
之类的数字并不困难。这是浮点算术期间丢失有效数字的问题。当您执行1 + (1 / x)
时,x
越大,将(1 / x)
部分添加到1时可以保留的有效数字越少,最终(1 / x)
就丢失了一词。
## valid 16 significant digits
1 + 1.23e-01 = 1.123000000000000|
1 + 1.23e-02 = 1.012300000000000|
... ...
1 + 1.23e-15 = 1.000000000000001|
1 + 1.23e-16 = 1.000000000000000|
任何数值分析书都会告诉您以下内容。
a + b = a * (1 + b / a)
中,如果b / a < 2.22e-16
,则有a + b = a
。这意味着当将多个正数相加时,将它们从最小到最大累加会更稳定。还建议您阅读Approximation to constant "pi" does not get any better after 50 iterations,这是在您提问几天后问到的一个问题。使用series逼近无理数在数值上是稳定的,因为您不会在问题中看到荒谬的行为。但是有限数量的有效有效数字会带来一个不同的问题:数值收敛,即,您只能将目标值近似化为一定数量的有效数字。 MichaelChirico's answer使用泰勒级数将在19个项后收敛,因为1 / factorial(19)
在加到1时已经在数字上为0。
浮点数之间的乘法/除法不会导致有效数字出现问题;它们可能会导致“上溢”或“下溢”。但是,鉴于可表示的浮点值范围很广(1e-308〜1e + 307),“上溢”和“下溢”应该很少。真正的困难在于加/减,其中很容易丢失有效数字。有关矩阵计算的示例,请参见Can I stably invert a Vandermonde matrix with many small values in R?。达到更高的精度并非不可能,但工作可能会涉及更多。例如,矩阵示例的OP最终使用GMP (GNU Multiple Precision Arithmetic Library)和相关的R包继续进行:How to put Rmpfr values into a function in R?
答案 1 :(得分:3)
您还可以尝试泰勒级数逼近exp(1)
,
e^x = \sum_{k = 0}{\infty} x^k / k!
因此,我们可以通过截断该和来逼近e = e^1
;在R中:
sprintf('%.20f', exp(1))
# [1] "2.71828182845904509080"
sprintf('%.20f', sum(1/factorial(0:10)))
# [1] "2.71828180114638451315"
sprintf('%.20f', sum(1/factorial(0:100)))
# [1] "2.71828182845904509080"