我正在学习Matlab,我不明白为什么
(eps * 0.5) + 1
不大于1。
eps
ans =
2.220446049250313e-16
fprintf('%.52f\n', eps);
0.0000000000000002220446049250313080847263336181640625
sign(eps)
ans =
1
% 1 means that eps is >= 0
eps >= 0
ans =
logical
1
eps > 0
ans =
logical
1
eps < 0
ans =
logical
0
% so, now I take half of eps
my_half_eps = eps * 0.5;
my_half_eps
my_half_eps =
1.110223024625157e-16
fprintf('%.52f\n', my_half_eps);
0.0000000000000001110223024625156540423631668090820312
sign(my_half_eps)
ans =
1
% half eps is positive
my_half_eps >= 0
ans =
logical
1
my_half_eps > 0
ans =
logical
1
my_half_eps < 0
ans =
logical
0
fprintf('%.52f\n', (eps + 1));
1.0000000000000002220446049250313080847263336181640625
% correct
fprintf('%.52f\n', (my_half_eps + 1));
1.0000000000000000000000000000000000000000000000000000
% WHAT ???
diary off
我认为
eps
是我可以加到 1 的最小数字。那么,向小于 eps
的数字加 1 会出现这个问题吗?
执行加法或几乎任何浮点运算时,正确舍入的结果1就像:
最常见的舍入规则是四舍五入到最接近的可表示数字,如果出现平局,则四舍五入到具有偶数低位的数字。2
在
double
精度常用的格式中,1表示为:
+1.0000000000000000000000000000000000000000000000002•20
(我已将最后一位数字标记为粗体,以直观地标记其位置)。下一个可代表的数字是
+1.0000000000000000000000000000000000000000000000012•20
eps
,所谓的“机器epsilon”是:
+0.0000000000000000000000000000000000000000000000012•20
所以 1 加 ½
eps
的实数运算结果为:
+1.00000000000000000000000000000000000000000000000012•20
查看 1、½
eps
+ 1 的实数结果以及下一个可表示数,我们可以看到 ½ eps
+ 1 正好位于两个可表示数之间的中间:
+1.0000000000000000000000000000000000000000000000002•20 +1.00000000000000000000000000000000000000000000000012•20 +1.0000000000000000000000000000000000000000000000012•20
因此,将 1/2
eps
加 1 的浮点运算将产生偶数低位的邻居,即 1.00000000000000000000000000000000000000000000000002•20 = 1.
如果将 ⅝
eps
加到 1,结果将是下一个可表示的数字 1.0000000000000000000000000000000000000000000000012•20,因为实数结果将通过中点,所以四舍五入将是到下一个数字。
1 诸如正弦和幂(指数)之类的困难运算通常是通过不正确的舍入来实现的。这仅适用于单个操作;多个操作的序列通常不会产生正确的舍入结果,除非专门设计和记录。
2 在严格限制的格式中,一位数精度下,两个邻居都可能以奇数位结尾,如 9•100 和 1•101。在这种情况下,使用幅度较大的数字。