我有一个简短的问题,关于在MatLab中可以用来计算符号表达式的vpa命令。
我的课本上是这样说的:
在对数字使用sqrt等函数时需要小心,默认情况下会产生双精度浮点数。您需要将此类输入作为符号字符串传递给vpa以进行正确的计算:vpa('sqrt(5)/pi')。
我不太明白这里的行话。为什么对于大多数输入,无论我输入的是vpa(input)还是vpa('input'),我得到的答案都是完全相同的,而对于平方根却不是这样?例如,如果我键入vpa(sin(pi/4))或vpa('sin(pi/4)'),我将得到完全相同的答案,但如果我键入vpa(sqrt(5)/pi)作为上面的给定问题,我将不会得到与键入vpa('sqrt(5)/pi')时相同的答案。
如果有人能比我上面的书更详细地解释这一点,我将不胜感激!
发布于 2012-06-04 02:51:46
我不是MatLab专家,但是没有引号,您就是将sqrt(5)/pi的结果传递给vpa()
vpa(sqrt(5)/pi)
= vpa(0.7117625434171772)使用引号将表达式sqrt(5)/pi (未求值的精确形式)传递给vpa(),然后告诉MatLab以可变精度计算sqrt(5)/pi。
发布于 2012-06-04 04:25:24
永远不要假设像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作为双精度数字传递时也是如此。由于圆周率(作为双精度)不是正确的过去的第16位小数,有一些可疑的事情正在发生。
>> vpa(pi,100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
>> vpa('pi',100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
vpa('pi',100) - vpa(pi,100)
ans =
0.0作为对这一事实的测试,让我们看看HPF发现了什么。HPF实际上采用存储在双精度型中的IEEE754值,然后将其转换为HPF数字。
>> hpf(pi,100)
ans =
3.141592653589793115997963468544185161590576171875
>> hpf('pi',100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
>> hpf('pi',100) - hpf(pi,100)
ans =
0.0000000000000001224646799147353177226065932275001058209749445923078164062862089986280348253421170679821480800000000很明显,MATLAB能够识别π,而不仅仅是传递给它的双精度值。
Edit2:
事实上,稍微玩玩一下就能告诉我这里发生了什么。VPA是一个棘手的问题,而不是解析器。考虑分数7/13。如果我们将其构建为双精度,然后打印出存储在其完全荣耀中的浮点值,我们看到它并不是真正精确的。这和预期的一样。
>> sprintf('%.100f',7/13)
ans =
0.53846153846153843591793020095792599022388458251953125000000000000000000000000000000000000000000000007/13是一个重复的十进制值。以下是正确的数字:
>> vpa('7/13',100)
ans =
0.5384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615385现在,假设我们尝试创建相同的数字。在这里,我将传递7/13作为双精度,但我会在小数点后数位中犯错误
>> 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发布于 2012-06-04 02:55:45
如果你得到了完全相同的答案,你一开始就不需要变精度的算术。
然而,sin(pi/4)应该恰好是sqrt(2)/2,这是不合理的。你不应该从不同的精度得到完全相同的答案。也许你应该检查一下你是如何显示(和舍入)结果的。
https://stackoverflow.com/questions/10872933
复制相似问题