永远不要假设像vpa(sin(pi / 4))这样的数字精确到完全精度,因为MATLAB通常会使用浮点运算来计算vpa调用内的数字,因此只能精确到大约16位数。
但是,它似乎在这里是正确的。例如,我们知道这一点
sin(pi/4) == sqrt(2)/2让我们测试一下结果。我将使用100位数的精度,比较vpa和我自己的HPF工具。
>> vpa(sin(pi/4),100)
ans =
0.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207864
>> vpa(sqrt(sym(2))/2,100)
ans =
0.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207864
>> sqrt(hpf(2,100))/2
ans =
0.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207864
>> sin(hpf('pi',100)/4)
ans =
0.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207864因此,我的猜测是解析器已将输入识别为符号工具箱可以更准确地计算的内容。正如我之前所说,但要小心。什么是罪(pi / 12)?
>> vpa(sin(pi/12),100)
ans =
0.25881904510252073947640383266843855381011962890625
>> vpa('sin(pi/12)',100)
ans =
0.2588190451025207623488988376240483283490689013199305138140032073150569747488019969223679746942496655
>> vpa(sin(sym('pi')/12),100)
ans =
0.2588190451025207623488988376240483283490689013199305138140032073150569747488019969223679746942496655
>> sin(hpf('pi',100)/12)
ans =
0.2588190451025207623488988376240483283490689013199305138140032073150569747488019969223679746942496655在第一种情况下,解析器没有保存我们。在其他人中,我强迫MATLAB计算正确的值。事实上,一些努力会给我们sin(pi / 12)的价值,如sqrt(2)*(sqrt(3) - 1)/ 4。
>> DefaultNumberOfDigits 100
>> (sqrt(hpf(3)) - 1)*sqrt(hpf(2))/4
ans =
0.2588190451025207623488988376240483283490689013199305138140032073150569747488019969223679746942496655关键是,不要相信解析器在这里保存你。
编辑:作为Amro评论的测试,我恭敬地说MATLAB在这里做了一些有趣的事情。看到vpa能够返回pi的正确的前100位数,即使作为双精度数传递pi也是如此。因为pi(作为一个双精度数)在第16个十进制数字之后是不正确的,所以有一些可疑的事情发生了。
>> vpa(pi,100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
>> vpa('pi',100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
vpa('pi',100) - vpa(pi,100)
ans =
0.0作为对这一事实的测试,让我们看看HPF发现了什么。 HPF实际上采用IEEE 754值,如存储在double中,然后将其转换为HPF编号。
>> hpf(pi,100)
ans =
3.141592653589793115997963468544185161590576171875
>> hpf('pi',100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
>> hpf('pi',100) - hpf(pi,100)
ans =
0.0000000000000001224646799147353177226065932275001058209749445923078164062862089986280348253421170679821480800000000很明显,MATLAB能够将pi识别为不仅仅是传递的双精度值。
EDIT2:
事实上,一些戏剧告诉我这里发生了什么。 VPA是棘手的,而不是解析器。考虑7/13分数。如果我们将它构建为double,那么打印出存储在其完整荣耀中的浮点值,我们认为它并不是真正准确的。这是预期的。
>> sprintf('%.100f',7/13)
ans =
0.53846153846153843591793020095792599022388458251953125000000000000000000000000000000000000000000000007/13是重复的十进制值。这是正确的数字:
>> vpa('7/13',100)
ans =
0.5384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615385现在,假设我们尝试创建相同的数字。在这里我将以7/13的速度传递asa double,但我会在底部的十进制数字中出错
>> sprintf('%.100f',0.538461538461538461777777777)
ans =
0.5384615384615384359179302009579259902238845825195312500000000000000000000000000000000000000000000000在这里,我们看到vpa捕获并纠正了我所做的'错误',认识到我传入的内容实际上与我在7/13中传递时的值相同。
>> vpa(0.538461538461538461777777777,100)
ans =
0.5384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615385当然,如果我将值作为字符串传递,那么vpa就会出错。
>> vpa('0.538461538461538461777777777',100)
ans =
0.538461538461538461777777777这解释了为什么vpa能够捕获并正确计算vpa(sin(pi / 4),100),达到所要求的全部精度。 sin(pi / 4)被计算为double,但是vpa将其视为与sqrt(2)/ 2的双精度版本相同的数字。
当然要小心。例如,vpa不够智能,无法捕捉pi的这种简单转变。
>> vpa(pi + 1,100)
ans =
4.141592653589793115997963468544185161590576171875
>> vpa(pi,100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068