解析,表达式
应该给0。
但是,在 Matlab 中,它没有。
x = linspace(1, 10, 10);
exp(log(x)) - x;
对于,答案是
0
0
-4.44089209850063e-16
0
0
0
0
-1.77635683940025e-15
1.77635683940025e-15
1.77635683940025e-15
发生了什么,我该如何解决这个问题?
解析,表达式
应该给0。
但是,在 Matlab 中,它没有。
x = linspace(1, 10, 10);
exp(log(x)) - x;
对于,答案是
0
0
-4.44089209850063e-16
0
0
0
0
-1.77635683940025e-15
1.77635683940025e-15
1.77635683940025e-15
发生了什么,我该如何解决这个问题?
数值精度并不完美。在计算过程中会出现舍入错误。使用浮点数时,不要检查它们是否 = 0,而是检查它们到 0 的绝对距离是否小于某个 epsilon。
[编辑] 另一种观点:64 位浮点数表示离散集。要使函数完全可逆,它应该是从到的双射。假设我们对像这样快速增长的函数感兴趣。在某一时刻,。如果是中的最大元素,则。严格版本是不允许的,因为中. 从道德上讲,像有限集上的双射一样的单调函数是一个排列,并且具有非常有限的自由度,它可能仅限于恒等式,或者是反转集合中元素顺序的反恒等式. 在这些琐碎的例子之外,单调函数不能是双射。
在实践中,这是由于有限精度的数值计算(例如64-bit
浮点),尤其会影响涉及无理数的函数。整数或二次幂和的计算可能不太敏感。如果你敢于绘制数值误差,你会得到类似的东西:
带Matlab
代码
x=linspace(1,10000,10000);
y = exp(log(x))-x;
plot(x,y,'.');
xlabel('x');
ylabel('y');
所以你可以看到最大误差随着值的传播。如果你想做某事,你可以检查和限制一个相对误差,特别是如果你的变量分布在一个很大的范围内。
更奇怪的是,如果你只是交换函数,比如:,在这种情况下,错误的数值为零。
x=linspace(1,700,10000);
y = log(exp(x))-x;
plot(x,y,'.');
xlabel('x');
ylabel('y');
基本问题是通常在使用固定精度浮点格式时。由于pidgeonhole 原理,这与计算指数函数和对数函数的精度无关。
在不失一般性的情况下,通过将二进制对数log2
与 IEEE-754 二进制浮点格式之一结合使用,最容易证明这种效果。使用这种格式,每个二进制文件都包含相同数量的编码。如果我们计算log2
两个连续的binade和所有结果都将落入单个binade中。由于可用的源编码是目标编码的两倍,因此根据 pidgeonhole 原理,我们必须有大量的冲突。
所有对数都是收缩运算。这意味着当使用固定精度浮点计算时,多个输入可以映射到同一个输出。由于这种压缩,信息会丢失,因此,当我们将中的数字扩展回时,对于许多,即使两个函数都正确使用了全面实施。exp2
颠倒操作顺序,即使用扩展操作后跟收缩逆操作,我们有时可以保证每个操作数往返成功,只要没有中间溢出或下溢,并假设正确舍入操作。我不知道(副手)这是否保证,但Laurent Duval 的回答中的图表似乎暗示了这一点。本文表明,的平方根恰好是。
如果您有符号工具箱,您可以通过以下方式解决问题
syms x
y = exp(log(x))-x
% y = 0