我一直以为MATLAB变量默认是双精度的。因此,如果我声明一个变量,在小数点后面有20个数字:
>> num = 2.71828182845904553488;
>> class(num) % Display the variable type
ans =
double
我期望最后4位数字被忽略,因为浮点数相对精度在10的-16次方数量级上:
>> eps(num)
ans =
4.440892098500626e-016
如果我尝试使用fprintf
或sprintf
显示小数点后超过16位的数字,我会得到预期结果:
>> fprintf('%0.20f\n', num)
2.71828182845904550000
>> sprintf('%0.20f', num)
ans =
2.71828182845904550000
换句话说,数字17到20都是0。
但当我将
num
传递给符号工具箱中的变量精度算术函数时,事情变得奇怪起来,我告诉它使用21位数字表示这个数字:>> vpa(num, 21)
ans =
2.71828182845904553488
什么?!那最后四位数字又出现了!当我输入的原始数字存储为双精度变量num
时,它们不应该已经丢失了吗?由于num
是一个双精度变量,当它传递给vpa
时,vpa
怎么知道它们是什么?我猜测 MATLAB 在内部使用比双倍精度更高的精度来表示
num
,因为我将其初始化为一个小数点后有更多位数的数字,而这超出了双精度变量的处理范围。这真的是正在发生的事情吗,还是其他事情正在发生?
额外奖励: 如果以上内容还没有让你头痛的话,这里有一个额外的混淆源...
>> num = 2.71828182845904553488; % Declare with 20 digits past the decimal
>> num = 2.718281828459045531; % Re-declare with 18 digits past the decimal
>> vpa(num, 21)
ans =
2.71828182845904553488 % It's the original 20-digit number!!!
fprintf('%bx\n', exp(1), 2.7182818284590455, 2.71828182845904559999999999)
,它们将返回相同的64位表示4005bf0a8b14576a
。 - Amrofprintf('%bx\n',exp(1),exp(1)+eps(exp(1)))
(至少对于这个值)。我将在我的答案中附带这一点。 - Andrew Janke