(0.3)^ 3 ==(0.3)*(0.3)*(0.3)在matlab中返回false?

Nic*_*ick 19 floating-point matlab

我试图理解MATLAB中基本算术运算的舍入误差,我遇到了以下奇怪的例子.

(0.3)^3 == (0.3)*(0.3)*(0.3)

ans = 0
Run Code Online (Sandbox Code Playgroud)

我想确切地知道如何计算左侧.MATLAB文档表明,对于整数幂,使用"通过平方取幂"算法.

"矩阵功率.如果p是标量,则X ^ p是功率p的X.如果p是整数,则通过重复平方来计算功率."

所以,我认为(0.3)^3(0.3)*(0.3)^2会返回相同的值.但这种情况并非如此.如何解释舍入误差的差异?

Jer*_*ten 5

我对MATLAB一无所知,但我在Ruby中尝试过:

irb> 0.3 ** 3
  => 0.026999999999999996
irb> 0.3 * 0.3 * 0.3
  => 0.027
Run Code Online (Sandbox Code Playgroud)

根据Ruby源代码,如果左侧操作数是浮点数,则取幂运算符将右侧操作数转换为浮点数,然后调用标准C函数pow().函数的float变体pow()必须实现更复杂的算法来处理非整数指数,这将使用导致舍入误差的操作.也许MATLAB的工作方式类似.


Ema*_*ini 3

感谢@Dougal,我发现了这个:

#include <stdio.h>
int main() {
  double x = 0.3;
  printf("%.40f\n", (x*x*x));

  long double y = 0.3;
  printf("%.40f\n", (double)(y*y*y));
}
Run Code Online (Sandbox Code Playgroud)

这使:

0.0269999999999999996946886682280819513835
0.0269999999999999962252417162744677625597
Run Code Online (Sandbox Code Playgroud)

这种情况很奇怪,因为更多位数的计算给出了最差的结果。这是因为无论如何初始数字 0.3 都是用几个数字来近似的,因此我们从一个相对“大”的误差开始。在这种特殊情况下,发生的情况是,用几个数字进行的计算给出了另一个“大”误差,但符号相反......因此补偿了初始误差。相反,使用更多位数的计算会给出第二个较小的误差,但第一个误差仍然存在。

  • 我得到了它!发生的情况是一种奇怪的情况,其中两个具有相反符号的较大误差的叠加(偶然)给出一个较小的误差,然后相同的第一个误差与较小的第二个误差但具有相同符号的叠加产生较小的误差。 (3认同)