matlab控制运算精度函数digits(A)和vpa(B)的使用方法

format这个函数不是用于控制运算精度的,它只能控制结果显示类型。运算的时候还是用matlab自己的精度,具体是多少就不知道了。

  matlab控制运算精度用的是digits和vpa这两个函数。

  digits用于规定运算精度,比如:

  digits(20);

  这个语句就规定了运算精度是20位有效数字。但并不是规定了就可以使用,因为实际编程中,我们可能有些运算需要控制精度,而有些不需要控制。vpa就用于解决这个问题,凡是用需要控制精度的,我们都对运算表达式使用vpa函数。例如:

  digits(5);

    a=vpa(sqrt(2));

  这样a的值就是1.4142,而不是准确的1.4142135623730950488016887242097......

  又如:

  digits(5);

    a=vpa(sqrt(2));

  b=sqrt(2);

  这样a的值是1.4142,b没有用vpa函数,所以b是1.4142135623730950488016887242097......

  vpa函数对其中每一个运算都控制精度,并非只控制结果。

  digits(11);

  a=vpa(2/3+4/7+5/9);

  b=2/3+4/7+5/9;

  a的结果为1.7936507936,b的结果为1.793650793650794......也就是说,计算a的值的时候,先对2/3,4 /7,5/9这三个运算都控制了精度,又对三个数相加的运算控制了精度。而b的值是真实值,对它取11位有效数字的话,结果为1.7936507937,与a不同,就是说vpa并不是先把表达式的值用matlab本身的精度求出来,再取有效数字,而是每运算一次,都控制精度。

  vpa对它括起来的运算每一次都控制精度,但有一点需要注意,vpa对函数的参数不起作用

  举一个例子:

  digits(5);

  a=vpa(sqrt(2/3));

  b=vpa(sqrt(vpa(2/3)));

  结果a为0.81649,b为.81650。sqrt是一个函数,2/3是参数,也就是说,a式中,vpa对2/3是不起作用的,只对sqrt函数的返回值作用。如果想达到2/3的精度也要控制的效果,就要用b式,对参数也使用vpa函数。

  还有一点,digits这个函数不是必需的,vpa可以这样用:

  vpa(表达式,运算精度);

  举例来说:

  vpa(pi,5);

  和

  digits(5);

  vpa(pi);

  结果是一样的,vpa不指定运算精度,就用digits函数指定的。如果也没有用digits函数,那就是按matlab本身的精度来运算。


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

最近使用matlab编程中需要高精度的计算(1.0E-15)左右的精度,有效数字大概为30。开始因为vpa很好的解决了问题,但是计算结果总是不对,被逼无奈投靠mathematica,最后发现是使用vpa的问题,现简单举例如下:
使用MATLAB 2012b 计算下面的结果存在差异,很困惑,不知何故:
K>> vpa((1+sqrt(5))/2,30)
ans =
1.61803398874989490252573887119


K>> vpa('(1+sqrt(5))/2',30)
ans =
1.61803398874989484820458683437


Mathematica的计算结果为1.61803398874989484820458683437
开始以为vpa的作用类似于mathematica里的N[],还非常高兴,觉得以后可以根据自己需要设置计算精度了,可是这好像不对啊,求各位高中不吝赐教,非常感谢


Ans:

vpa((1+sqrt(5))/2,30)
这种方式只不过是把1+sqrt(5))/2的结果传入符号计算引擎,而1+sqrt(5))/2是通过数值计算得到的一个浮点数,本身就有误差,所以符号计算引擎并不一定能识别出这个浮点数的准确值
而vpa('(1+sqrt(5))/2',30)或者vpa(sym('(1+sqrt(5))/2'),30)引擎得到的是表达式,所以可以按照你指定的精度运算


Q:啊,是的,我在网上又查了一些资料,确实如此,现在我碰到的实际问题是这样的:
Matlab代码:
a = sym('6378137');
b = sym('6356752.3142451795');
e = sym(sqrt((a^2-b^2)/a^2));
n = sym( (1 - sqrt(1-e^2)) / (1 + sqrt(1-e^2)) );
lat=sym('pi/18');
Hyperg = sym(1 - n + 5*n^2/4 - 5*n^3/4 + 81*n^4/64 - 81*n^5/64 + 325*n^6/256);

B = sym(3/2*n - 9/16*n^3 + 3/32*n^5);
C = sym(15/16*n^2 - 15/32*n^4 + 135/2048*n^6);
D = sym(35/48*n^3 - 105/256*n^5);
E = sym(315/512*n^4 - 189/2048*n^6);
F = sym(693/1280*n^5);
G = sym(1001/2048*n^6);
S =  sym(a*Hyperg*(lat - B*sin(2*lat) + C*sin(4*lat) - D*sin(6*lat) + E*sin(8*lat) - F*sin(10*lat) + G*sin(12*lat)));
计算出来vpa(S, 30) = 1105854.83323437225492394711836

而mathematica计算结果是1105854.83323437221600005686969 请问是我程序有问题吗?

Ans:matlab计算的结果没什么问题,我用mathematica算出来也是这个值
可能你的mathematica代码有问题

Q:我又遇到了个新的问题,还请麻烦你指导一下,不胜感激。
我这样命名了一个数组
S=sym([1.10585483323437221594951521850*10^6, 
2.21236625417163346388516283428*10^6, 
3.32011339794038290699715786406*10^6, 
4.42952903035051543447494476041*10^6, 
5.54084704168414870342507842902*10^6, 
6.65407281949051174008062343589*10^6, 
7.76898072777019372393782026723*10^6, 
8.88513987193687311569493018429*10^6, 
1.00019657293127228136512645312*10^7]);

可是现实的时候却精度不对
vpa(S,30)结果为
ans =
1105854.83323437231592833995819
2212366.25417163316160440444946
3320113.39794038282707333564758
4429529.03035051561892032623291
5540847.04168414883315563201904
6654072.81949051190167665481567
7768980.72777019347995519638062
8885139.87193687260150909423828
  10001965.729312723502516746521
精度不对,请问我应该怎么赋值才正确呢?

Ans:这和之前所说的情形是一样的,矩阵是首先生成后才传给sym函数,而矩阵生成并不涉及符号运算,所以sym得到矩阵之前精度已经损失了


Q:那除了这样的方法
=[sym('1.10585483323437221594951521850*10^6'), 
sym('2.21236625417163346388516283428*10^6'), 
sym('3.32011339794038290699715786406*10^6'), 
sym('4.42952903035051543447494476041*10^6'), 
sym('5.54084704168414870342507842902*10^6'), 
sym('6.65407281949051174008062343589*10^6'), 
sym('7.76898072777019372393782026723*10^6'), 
sym('8.88513987193687311569493018429*10^6'), 
sym('1.00019657293127228136512645312*10^7')]);
请问还有别的方法吗?

Ans:S =vpa(['[1.10585483323437221594951521850*10^6,'... 
'2.21236625417163346388516283428*10^6,'... 
'3.32011339794038290699715786406*10^6,'...
'4.42952903035051543447494476041*10^6,'... 
'5.54084704168414870342507842902*10^6,'...
'6.65407281949051174008062343589*10^6,'...
'7.76898072777019372393782026723*10^6,'...
'8.88513987193687311569493018429*10^6,'...
'1.00019657293127228136512645312*10^7]'],30);

  • 22
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值