Theoretical Intelligence分享 http://blog.sciencenet.cn/u/felonwan

博文

C语言数值计算版

已有 7152 次阅读 2013-12-21 01:24 |个人分类:程序世界|系统分类:生活其它| C语言, Perl, 数值计算, 幂函数, 括号配对

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脚本,边学边写的。

另外可以参考相关讨论和网友zhao4zhong1的C语言版本源代码:http://bbs.csdn.net/topics/390671469


https://blog.sciencenet.cn/blog-335776-751582.html

上一篇:虚拟世界的电子云
下一篇:《计算机与人脑》笔记
收藏 IP: 210.26.51.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-4-19 20:30

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部