简体   繁体   English

R:计算 log(exp(…)) 的最大浮点误差

[英]R: Computing maximum floating-point error for log(exp(…))

I am working on some programming problems where I have to transition probabilities between standard space and log-space.我正在解决一些必须在标准空间和对数空间之间转换概率的编程问题。 For this purpose, I am trying to find out the maximum absolute error for the floating-point error in R for the computation log(exp(...)) where the input is a log-probability (ie, a non-positive number).为此,我试图找出R浮点误差最大绝对误差,用于计算log(exp(...))其中输入是对数概率(即非正数)。

At the moment I have computed the answer by using a grid search (see code and plot below), but I'm not sure if the value I've computed is correct.目前我已经使用网格搜索计算了答案(见下面的代码和图),但我不确定我计算的值是否正确。 (I checked some other ranges but the range shown in the plot seems to get the maximum absolute error.) (我检查了一些其他范围,但图中显示的范围似乎获得了最大绝对误差。)

#Set function for computing floating-point error of log(exp(...))
fp.error <- function(x) { abs(log(exp(x)) - x) }

#Compute and plot floating-point error over a grid of non-negative values
xx <- -(0:20000/10000)
ff <- fp.error(xx)
plot(xx, ff, col = '#0000FF10',
     main = 'Error in computation of log(exp(...))', 
     xlab = 'x', ylab = 'Floating-Point Error')

#Compute maximum floating-point error
fp.error.max <- max(ff)
fp.error.max
[1] 1.110223e-16

在此处输入图片说明

From this analysis, my estimated maximum absolute error is half the size of .Machine$double.eps (which is 2.220446e-16 ).从这个分析中,我估计的最大绝对误差是.Machine$double.eps大小的一半(即2.220446e-16 )。 I am not sure if there is a theoretical reason for this, or if I am getting the wrong answer.我不确定这是否有理论上的原因,或者我是否得到了错误的答案。

Question: Is there any way to determine if this is really the maximum floating-point error for this computation?问题:有什么方法可以确定这是否真的是此计算的最大浮点误差? Is there any theoretical way to compute the maximum, or is this kind of grid-search method sufficient?是否有任何理论方法来计算最大值,或者这种网格搜索方法是否足够?

I think you got the right answer.我想你得到了正确的答案。 Here I refined the step as small as sqrt(.Machine$double.eps) , you will see在这里,我将步骤细化为sqrt(.Machine$double.eps) ,你会看到

> x <- seq(0, 2, by = sqrt(.Machine$double.eps))

> max(abs(log(exp(x)) - x))
[1] 1.110725e-16

However, once your x is extremely large, you will have Inf error, eg,然而,一旦你的x非常大,你就会有Inf错误,例如,

> (x <- .Machine$double.xmax)
[1] 1.797693e+308

> max(abs(log(exp(x)) - x))
[1] Inf

The error of log(exp(x)) depends on the value of x . log(exp(x))的误差取决于x的值。 If you use a float also x has an precision which depending on its value.如果您使用浮点数,则x 也具有取决于其值的精度。 The precission could be calculated with nextafter from C :可以从C使用nextafter计算精度:

library(Rcpp)
cppFunction("double getPrec(double x) {
  return nextafter(x, std::numeric_limits<double>::infinity()) - x;}")

getPrec(2)
#[1] 4.440892e-16

getPrec(exp(2))
#[1] 8.881784e-16

or not using Rcpp :或不使用Rcpp

getPrecR <- function(x) {
  y <- log2(pmax(.Machine$double.xmin, abs(x)))
  ifelse(x < 0 & floor(y) == y, 2^(y-1), 2^floor(y)) * .Machine$double.eps
}

Have also a look at: What is the correct/standard way to check if difference is smaller than machine precision?也看看:检查差异是否小于机器精度的正确/标准方法是什么? . .

In general, I'd suggest using a randomised approach to generate a lot more x s, eg:一般来说,我建议使用随机方法来生成更多x s,例如:

x <- runif(10000000, 0, 2)

Your regularly spaced values might happen to stumble on a pattern that "just works".您的定期间隔值可能碰巧偶然发现了一种“有效”的模式。

Also it depends on whether you care about absolute error or relative error .也取决于您是否关心绝对误差或相对误差 The absolute error should be close to .Machine$double.xmax while relative error increases as x approaches zero.绝对误差应该接近.Machine$double.xmax而相对误差随着x接近零而增加。 Eg log(exp(1e-16)) gets truncated to zero.例如log(exp(1e-16))被截断为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM