我的问题如下:在
0 : 0.2 : 10
函数中写入冒号符号 linspace
并编写一个命令,使两者的差值看起来为 0。
我尝试以下代码:
A = 0 : 0.2 : 10
B = linspace(0, 10, 51)
A - B
但是,它给出以下输出
ans =
Columns 1 through 6:
0 0 0 0 0 0
Columns 7 through 12:
0 0 0 0 0 0
Columns 13 through 18:
0 0 0 0 0 0
Columns 19 through 24:
0 0 0 0 0 0
Columns 25 through 30:
0 0 8.8818e-16 8.8818e-16 8.8818e-16 8.8818e-16
Columns 31 through 36:
0 8.8818e-16 0 8.8818e-16 8.8818e-16 0
Columns 37 through 42:
8.8818e-16 0 8.8818e-16 8.8818e-16 0 1.7764e-15
Columns 43 through 48:
0 0 0 0 1.7764e-15 0
Columns 49 through 51:
1.7764e-15 0 0
非零元素困扰着我。我想我已经完成了
linspace
部分。如何形成命令以使差异被视为零?我需要一些提示。请尝试在不使用高级工具的情况下尽可能地提示命令!
为了理解发生了什么,不要试图理解“有限的二进制精度”、“不能完全用二进制表示的数字”的概念,而是考虑“十进制精度”和“不完全可以表示的数字”上下文中的等效情况可以用十进制表示。为了方便起见,让我们考虑一个更简单的问题:
A = 0 : 1/6 : 1
B = linspace( 0, 1, 7 )
我们假设我们的 CPU 精确到 4 位有效数字。
关于A;在这里,我们注意到 1/6 不能直接用十进制表示。因此,我们的十进制 CPU 会将其转换为最接近的十进制表示形式,即 0.1667。因此范围将变为:
0,
0 + 0.1667 = 0.1667
0.1667 + 0.1667 = 0.3334
0.3334 + 0.1667 = 0.5001
0.5001 + 0.1667 = 0.6668
0.6668 + 0.1667 = 0.8335
0.8335 + 0.1667 = 1.0002
关于B:内部,linspace算法会尝试执行以下计算:
B =
0/6 = 0.0000
1/6 = 0.1667
2/6 = 0.3333
3/6 = 0.5000
4/6 = 0.6667
5/6 = 0.8333
6/6 = 1.0000
因此,在具有 4 位有效数字精度的十进制系统中:
A-B =
0
0
0.0001
0.0001
0.0001
0.0002
0.0002
二进制也有类似的情况;值 0.2 不能“精确地”用二进制表示,因此它是近似值。在“范围”中,它被重复添加。在“linspace”中,除法在内部进行,如果输出不能完全被 2 整除,则输出是近似值。
所以你的问题“如何让 A-B 恰好为 0”并不是选择“更好的函数”的问题。这是一个拥有无限精度的理论计算机来进行计算的问题。
因此,您问错了问题。正确的问题是,考虑到机器精度的某种程度的公差,这两个输出是否相同为零?可接受的容忍度是多少?
回答这个问题的一种方法是通过
assert
函数以及返回机器精度的 eps
函数,来查看两个变量在相对于 eps
的某个公差范围内是否相等:
try ; assert( A, B, eps ), disp('All elements are equal for the given tolerance')
catch; disp('Elements were not equal for the given tolerance')
end_try_catch
# Elements were not equal for the given tolerance
try ; assert( A, B, 10*eps ), disp('All elements are equal for the given tolerance')
catch; disp('Elements were not equal for the given tolerance')
end_try_catch
# All elements are equal for the given tolerance
在我的机器上,eps=2e-16。因此 A-B 为零,公差为 2e-15。这是否可以接受完全取决于您和问题的性质。但机器精度是计算机的固有限制,人们必须意识到它的存在以及它如何影响您对计算的解释。