我想我在 Matlab 中发现了一个错误。我唯一的解释是,matlab 在内部使用其他值而不是显示的值进行计算:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(ans)
ans =
3
显示的代码是 Matlab 控制台的输出。calc(x,y) 只是一个双精度值数组。
我想我在 Matlab 中发现了一个错误。我唯一的解释是,matlab 在内部使用其他值而不是显示的值进行计算:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(ans)
ans =
3
显示的代码是 Matlab 控制台的输出。calc(x,y) 只是一个双精度值数组。
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
你得到的是一个非常接近但低于 4 的值,即使使用format long
Matlab 也必须四舍五入到第 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 链接。
我不会讨论这个问题,而是提供一个解决方案:使用single
函数:
B = single(A) 将矩阵 A 转换为单精度,在 B 中返回该值。A 可以是任何数字对象(例如双精度)。如果 A 已经是单精度,则 single 无效。单精度数量比双精度数量需要更少的存储空间,但精度更低,范围更小。
这只是为了解决这个特定问题,所以你会这样做:
K>> calc(1,11)
ans =
4.000000000000000
K>> floor(single(ans))
ans =
4