2

我想我在 Matlab 中发现了一个错误。我唯一的解释是,matlab 在内部使用其他值而不是显示的值进行计算:

K>> calc(1,11)

ans =

   4.000000000000000

K>> floor(ans)

ans =

     3

显示的代码是 Matlab 控制台的输出。calc(x,y) 只是一个双精度值数组。

4

3 回答 3

8

MATLAB 使用标准 IEEE 浮点形式来存储双精度数。

看到如果我们从 4 中减去一小部分,MATLAB 仍然显示 4 作为结果。

>> format long g
>> 4 - eps(2)
ans =
                         4

事实上,MATLAB 以二进制形式存储数字。我们可以看到该数字的十进制版本为:

>> sprintf('%.55f',4-eps(2))
ans =
3.9999999999999995559107901499373838305473327636718750000

显然 MATLAB 不应该显示所有数字,但是通过将结果四舍五入为 15 位,我们得到 4 用于显示。

显然,calc(1,11) 中的值就是这样一个数字,在内部表示为小于 4,只是一根头发太少了,以至于它在显示时四舍五入到 4,但它不完全是 4。

永远不要相信浮点运算结果中显示的最低有效数字。

编辑:

您似乎认为 MATLAB 中的 3.999999999999999 应该小于 4。从逻辑上讲,这是有道理的。但是,当您提供该号码时会发生什么?啊,是的,浮点双精度的粒度比这大。MATLAB 不能将其表示为小于 4 的数字。它在内部将该数字向上四舍五入为 4。

>> sprintf('%.55f',3.9999999999999999)
ans =
4.0000000000000000000000000000000000000000000000000000000
于 2012-09-26T23:05:20.220 回答
3

你得到的是一个非常接近但低于 4 的值,即使使用format longMatlab 也必须四舍五入到第 15 位才能显示数字。尝试这个:

format long
asd = 3.9999999999999997 %first not-9 @16th digit

将打印4.000000000000000。任何不知道asd基于可视化的实际值的人都会猜测它至少是 4,但是运行

asd >= 4

给出0,所以floor(asd)返回3

Matlab如何对显示的输出进行四舍五入也是一个问题,存储在变量中的真实值小于4。

更新:

如果您进一步使用数字,例如 18x9:

>> asd = 3.999999999999999999
asd = 
     4
>> asd == 4
ans =
     1

asd就变成了4!(注意它不再显示4.000000000000000)但这是另一个故事,不再是关于将数字四舍五入以获得更漂亮的输出,而是关于浮点运算的工作原理......实数可以表示为一定的相对精度:在这种情况下,您给出的数字非常接近 4,以至于它本身变成了 4。查看@gokcehan 或此处的评论中发布的 Python 链接。

于 2012-09-26T22:49:23.220 回答
1

我不会讨论这个问题,而是提供一个解决方案:使用single函数:

B = single(A) 将矩阵 A 转换为单精度,在 B 中返回该值。A 可以是任何数字对象(例如双精度)。如果 A 已经是单精度,则 single 无效。单精度数量比双精度数量需要更少的存储空间,但精度更低,范围更小。

这只是为了解决这个特定问题,所以你会这样做:

K>> calc(1,11)

ans =

   4.000000000000000

K>> floor(single(ans))

ans =

 4
于 2015-03-26T01:42:58.800 回答