Matlab不仅在数值运算上功能强大,它也能负担一定程度的符号运算。
问题描述
最
近交给Matlab解一个比较大的方程组的符号结果遇到了一个问题。当我的运算结束以后Matlab把结果放在了一个个符号变量里面存着,在Workspace里面显示为1x1的sym类型变量,如果我要打印在屏幕上,可以直接敲变量名就可以在Command Window里面显示。但是,当解出来的符号结果过长,已经超出了Command Window能够显示的25000字符的宽度时,我们就不能直接获得运算结果打印在屏幕上,也就不能直接从屏幕上拷贝解析表达式,进一步进行编辑处理了。
...Output truncated.Text exceeds maximum line length of 25,000 characters for Command Window display.
解方程算出来的符号表达式的用处就是要赋值进去运算,得到预期结果,如果连表达式本身都看不到或者不能直接处理,那算出来还有什么用处呢?
解决思路
解决的思路有这么几点:
第一种方法,是可行的,但是存在运算速度的问题。对于symbolic expression,matlab是可以直接赋值处理的,而且赋值进行运算之后还不会对原始的解析表达式造成任何影响。赋值运算的命令是subs(substitution的简写,可以看得出其实是一个代值运算而不是真正意义上的赋值),具体操作可以help subs进行查看。简单的说,如果进行单变量代值,可以进行数值代换和符号代换。比如sym变量a、b、c和Sum,令Sum=a+2*b+3*c。把a=1带入,subs(Sum,a,1),得到的输出结果是ans = 2*b + 3*c + 1,而此时查看Sum依然是Sum = 2*b + 3*c + 1。所以subs命令的代值只会输出一个运算结果放在我们指定的地方(默认在ans变量里临时存储),而不会改变表达式的内容。符号代值,如subs(Sum,a,b),结果是ans = 3*b + 3*c。多变量代值可以用矩阵形式输入,如subs(Sum,[a,b,c],[1,2,3]),结果是14,达到了赋值的目的。同样不影响表达式本身。所以,如果不对表达式做处理,直接赋值是行得通的。下面接着是“但是”部分。
但是,这条命令有个致命的弱点,那就是运算速度很不理想。对于我所要进行的大运算量来说,这个运算时间简直就是慢得要命。简单举个例子,同样是赋值运算,sym的subs命令和数值变量的运算相比,运算时间明显是一个数量级的差别,subs命令慢得如此明显!
符号运算:
tic
syms a b c Sum
Sum = a + 2*b +3*c;
subs(Sum,[a,b,c],[1,2,3])
toc
数值变量运算:
tic
a=1;b=2;c=3;
a + 2*b + 3*c
toc
结果是符号运算三次的最佳值为0.030697秒,数值运算三次的最佳值为0.002868秒,仅仅是这么一个简单的运算,符号运算就花了10倍于数值运算的运算时间,这个速度简直不敢恭维。这
所以结论是,subs命令可行,但是速度太慢,大量运算就另寻高就吧。
第二种方法,经过努力,也是可行的。要输出为txt文件,用到fopen、fprintf和fclose命令。fopen命令用来新建文件,并用参数w表示无条件写入内容。fprintf直接开始写入内容,fclose结束。这样的话就可以不管屏幕上能不能够显示出来,输出到txt文件之后就可以直接编辑了。
但是,fprintf命令并不能直接将sym类型的变量内容直接打印出来,类型不支持。在help里面我看到fprintf是支持char类型变量的直接打印的,所以用char()命令进行一个类型转换就行了。举个例,我用的命令是:
fileID = fopen('H2f_H2s.txt','w');
fprintf(fileID,'H2f(1,nn)=%s;\n\n\n H2s(1,nn)=%s;',char(H2f),char(H2s));
fclose(fileID);
'Printed to file:H2f_H2s.txt'
这样就解决了表达式不能屏显的问题,再把文件里的公式编辑好之后拷贝到想用到的位置,就完事儿了。我把公示编辑好之后,用数值赋值运算进行计算,而不是subs,速度就甩了第一种方法三条街啊!