|||
C/C++效率高,用来做系统底层的设计无疑是很好的,但是现在也有很多人用来做数值计算。
不过C/C++并没有为数值计算优化。最简单的,比如:幂函数居然要写成pow(x,n)这样比较复杂的形式,如果使用x^n更符合直觉,更易用;复杂一点的,Fortran里有对矩阵的操作块的操作,C/C++里只能一个数一个数地操作。
如果能做一个编译器级别的改变肯定是最好的,引入一些对于数值计算更易用的语法,再引入一些数值计算库,这样或许可以开发一个C/C++数值计算的变种。不过这个事笔者目前是没有这能力。如果有人有能力而且感兴趣,不妨建个开源项目什么的。
易学易用是重要的一方面,但是功能的强大、方便扩展无疑更重要。如果这个C/C++的分支相对于原始C/C++及其它科学计算语言来说没有很大的优势,肯定做不起来,不如不做!目前Fortran做数值计算就比C易学易用一些;科学计算的库,也已经有很多了,有类似matlab矩阵操作的库函数,有符号计算的库;matlab、mathematica这样的脚本语言很成熟,易用扩展性强;结合C和python脚本的scipy和numpy这样的科学计算平台做得也很好,用的人不少。
这里,笔者介绍一个自己做的小东西。不改变标准C语法,只是写程序的时候:用$表示标准C语言中的按位异或,用^表示乘方,然后在预处理的时候再转换回去。(这种事情意义不大,如果能成为标准才有意义)。
下面是把“x^n”转变成“pow(x,n)”的Perl脚本,考虑各种可能的情况:
最终版本如下:
#!/usr/bin/perl
my \$levelN = qr/ (?> [^()]+ | \( (??{ \$levelN }) \) )* /x;
while (<STDIN>) {
(/\^/) while
s/(\w*\.*\w+|[pow]*\(\$levelN\))\s*\^\s*([pow]*\($levelN\)|\w+\.*\w*)/pow(\$1,\$2)/;
print "\$_";
}
用法cat filename.c | ./perfect new_filename.c
测试例子:
$ echo -e "a.b^(c+d)^(e-f/g^h*i)" | ./perfect
pow(pow(a.b,(c+d)),(e-f/pow(g,h)*i))
$ echo -e "^ (c+d) *^/ (e-f/g^h*i)" | ./perfect
^ (c+d) *^/ (e-f/pow(g,h)*i)
功能完整、不处理语法错误、健壮、很简洁。
默认a^b^c为(a^b)^c。
缺点:会有些非必要的括号。
最初的版本,加上规避a^b^c形式的功能,好处是具有去掉非必要括号功能,缺点是代码里面4种不同类型的字符替换代码重复度高、顺序不能变:
#!/usr/bin/perl
# dynamic regexp
my \$levelN = qr/ (?> [^()]+ | \( (??{ \$levelN }) \) )* /x;
# do the replacement and print to screen.
while(<STDIN>){
my \$line = \$_;
my \$line1 = \$line;
if(/\^\s*\(\$levelN\)\s*\^/ | /\^\s*\w*\.*\w*\s*\^/){die "Error: Form 'A^B^C' is not allowed, please clarify it as '(A^B)^C' or 'A^(B^C)'!";}
while(1){
\$line1=~ s/\((\$levelN)\)\s*\^\s*\((\$levelN)\)/pow(\$1,\$2)/g; #(a+b)^(c+d)
if("\$line1" eq "\$line"){last;}
\$line=\$line1;
}
while(1){
\$line1=~ s/(\w*\.*\w+)\s*\^\s*\((\$levelN)\)/pow(\$1,\$2)/g; #a^(b+c)
if("\$line1" eq "\$line"){last;}
\$line=\$line1;
}
while(1){
\$line1=~ s/\((\$levelN)\)\s*\^\s*(\w+\.*\w*)/pow(\$1,\$2)/g; #(a+b)^c
if("\$line1" eq "\$line"){last;}
\$line=\$line1;
}
while(1){
\$line1=~ s/(\w*\.*\w+)\s*\^\s*(\w+\.*\w*)/pow(\$1,\$2)/g; #a^b
if("\$line1" eq "\$line"){last;}
\$line=\$line1;
}
print "\$line"
}
用法:./topow filename.c >newname.c
第一次写的perl脚本,边学边写的。
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-11-24 01:21
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社