免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: dbcat

[原创] 表达式求值程序 by AWK  关闭 [复制链接]

论坛徽章:
7
荣誉版主
日期:2011-11-23 16:44:17子鼠
日期:2014-07-24 15:38:07狮子座
日期:2014-07-24 11:00:54巨蟹座
日期:2014-07-21 19:03:10双子座
日期:2014-05-22 12:00:09卯兔
日期:2014-05-08 19:43:17卯兔
日期:2014-08-22 13:39:09
发表于 2006-04-14 11:50 |显示全部楼层
功能加多了的话,一不小心一个新的脚本语言就此诞生了

论坛徽章:
0
发表于 2006-04-14 13:47 |显示全部楼层
呵呵,如果加sin log...的话,用一棵expression binary tree 来分析比较好。


更新链接


  1. #! /usr/bin/awk
  2. # expression evaluator awk version
  3. # author : dbcat at chinaunix
  4. # email: deeperbluecat@gmail.com
  5. # 用法:
  6. # echo "4*arctan(sin(1))+sqrt(1.2)*(1-23*exp(3))-log(2+cos(3))"| awk -f eval
  7. # echo "PI+E^sin(32.1%3.1)"|awk -f eval
  8. # awk -f eval <( seq 1 100|tr "\n" "+"|sed 's/+//100' )
  9. # echo '1!=2&1|0'|awk -f eval
  10. # echo '1<=2+3>=(!2-1.1)+sin(1.2*(PI!=E))' | awk -f eval
  11. # 支持的算术运算符号 : + - * / % ^ ( )
  12. # 支持的函数运算 : sin cos tg log exp arctan sqrt int
  13. # 支持的逻辑运算符号 : < > ! != <= >= & |
  14. # 内置的常数 : PI  E
  15. # 运行环境 : GNU Awk 3.1.4
  16. # have fun






  17. BEGIN{

  18. # 运算符集合
  19. symbol="+-*%<=!=>==|&>^SCLAEQTI/()@";
  20. # 构造运算符优先级关系
  21. consop(oppr);

  22. }







  23. #主函数

  24. {
  25.    split(funclib($0"@"),Ex," ");
  26.    print evaluate(Ex);
  27. }










  28. # 表达式求值函数

  29. function evaluate(Ex,OP,OF,c,k,t,x,str,y,r)
  30. {
  31.     k=1;
  32.     push(OP,"@");
  33.     c=Ex[k];
  34.     while(c!="@" || gettop(OP)!="@")
  35.       {
  36.         if(index(symbol,c)==0)
  37.           {
  38.             push(OF,c);
  39.             k=k+1;
  40.             c=Ex[k];

  41.           }else
  42.           {
  43.             t=priority(oppr,gettop(OP),c);
  44.             if(t=="<")
  45.              {
  46.                push(OP,c);
  47.                k=k+1;
  48.                c=Ex[k];

  49.              }else if(t=="=")
  50.              {

  51.                pop(OP);
  52.                k=k+1;
  53.                c=Ex[k];
  54.              }else{

  55.                str=pop(OP);
  56.                y=pop(OF);
  57.                x=pop(OF);
  58.                r=calculate(x,str,y);
  59.                push(OF,calculate(x,str,y));

  60.             }

  61.           }

  62.       }
  63.   return gettop(OF);
  64. }


  65. # 二元运算函数

  66. function calculate(x,st,y)
  67. {
  68.     if(st=="+")
  69.       return x+y;
  70.     else if(st=="-")
  71.       return x-y;
  72.     else if(st=="*")
  73.       return x*y;
  74.     else if(st=="%")
  75.       return x%y;
  76.     else if(st=="/")
  77.       return x/y;
  78.     else if(st=="^")
  79.       return x^y;
  80.     else if(st=="S")
  81.       return sin(y);
  82.     else if(st=="C")
  83.       return cos(y);
  84.     else if(st=="L")
  85.       return log(y);
  86.     else if(st=="E")
  87.       return exp(y);
  88.     else if(st=="Q")
  89.       return sqrt(y);
  90.     else if(st=="A")
  91.       return atan2(y,1);
  92.     else if(st=="T")
  93.       return sin(y)/cos(y);
  94.     else if(st=="I")
  95.       return int(y);
  96.     else if(st=="<")
  97.       return x<y;
  98.     else if(st==">")
  99.       return x>y;
  100.     else if(st=="<=")
  101.       return x<=y;
  102.     else if(st==">=")
  103.       return x>=y;
  104.     else if(st=="==")
  105.       return x==y;
  106.     else if(st=="!=")
  107.       return x!=y;
  108.     else if(st=="&")
  109.       return x&&y;
  110.     else if(st=="|")
  111.       return x||y;
  112.     else if(st=="!")
  113.       return !y;

  114. }




  115. # 算符优先关系函数
  116. function consop(oppr,t,x,y,z,i,k,j,xl,yl,zl,tl)
  117. {
  118.    xl="+-";
  119.    yl=" * / % ^ < <= ! & | > >= == != ";
  120.    zl="SCALEQTI";
  121.    tl="+ - * / % ^ < > ! != == >= <= & | S C A L E Q T I";
  122.    split(tl,t," ");
  123.    split(xl,x,"");
  124.    split(yl,y," ");
  125.    split(zl,z,"");

  126.    for(k=1;k<=length(xl);k++)
  127.      {
  128.        for(j=1;j<=length(xl);j++)
  129.         {
  130.           oppr[x[k]""x[j]]=">";
  131.           oppr[x[j]""x[j]]=">";
  132.         }
  133.        for(j=1;j<=length(yl);j++)
  134.         {
  135.           oppr[x[k]""y[j]]="<";
  136.           oppr[y[j]""x[k]]=">";
  137.           for(i=1;i<=length(yl);i++)
  138.             {
  139.               oppr[y[j]""y[i]]=">";
  140.               oppr[y[i]""y[j]]=">";
  141.             }
  142.           for(i=1;i<=length(zl);i++)
  143.             {
  144.                 oppr[y[j]""z[i]]="<";
  145.                 oppr[z[i]""y[j]]=">";
  146.             }
  147.         }
  148.       for(j=1;j<=length(zl);j++)
  149.         {
  150.           oppr[x[k]""z[j]]="<";
  151.           oppr[z[j]""x[k]]=">";
  152.           for(i=1;i<=length(zl);i++)
  153.            {
  154.               oppr[z[j]""z[i]]=">";
  155.               oppr[z[i]""z[j]]=">";
  156.            }
  157.         }
  158.      }



  159.        for(j=1;j<=length(tl);j++)
  160.         {
  161.            oppr[t[j]"("]="<";
  162.            oppr[t[j]")"]=">"
  163.            oppr[t[j]"@"]=">";
  164.            oppr[")"t[j]]=">";
  165.            oppr["("t[j]]="<";
  166.            oppr["@"t[j]]="<";
  167.         }
  168.       for(j=1;j<=length(yl);j++)
  169.        {
  170.            oppr[y[j]"^"]="<";
  171.        }

  172.    oppr["(("]="<";oppr["()"]="=";
  173.    oppr["))"]=">";oppr[")@"]=">";
  174.    oppr["@("]="<";oppr["@@"]="=";


  175. }






  176. # 优先级别比较

  177. function priority(oppr,op1,op2)
  178. {
  179.     return oppr[op1""op2];
  180. }






  181. # 分解表达式

  182. function funclib(expr)
  183. {

  184.    gsub(/PI/,"3.141592653589793238460",expr);
  185.    gsub(/E/,"2.718281828459045235360",expr);
  186.    gsub(/sin/," & S ",expr);
  187.    gsub(/cos/," & C ",expr);
  188.    gsub(/log/," & L ",expr);
  189.    gsub(/exp/," & E ",expr);
  190.    gsub(/arctan/," & A ",expr);
  191.    gsub(/sqrt/," & Q ",expr);
  192.    gsub(/tg/," & T ",expr);
  193.    gsub(/int/," & I ",expr);
  194.    gsub(/[-*%+>=!&|<^()SCLAEQTI/@]/," & ",expr);
  195.    gsub(/<[ ]*=/,"<=",expr);
  196.    gsub(/>[ ]*=/,">=",expr);
  197.    gsub(/=[ ]*=/,"==",expr);
  198.    gsub(/![ ]*=/,"!=",expr);
  199.    gsub(/&/," & ",expr);
  200.    gsub(/[|]/," & ",expr);
  201.    gsub(/![^=]/," N ! ",expr);

  202.    return expr;

  203. }




  204. # 取栈顶

  205. function gettop(arr,k,t)
  206. {
  207.     k=0;
  208.     for(t in arr)
  209.      {
  210.         k++;
  211.      }
  212.     return arr[k-1];
  213. }

  214. #  进栈函数

  215. function push(arr,x,t,k)
  216. {
  217.   k=0;
  218.   for(t in arr)
  219.    {
  220.       k++;
  221.    }
  222. arr[k]=x;

  223. }


  224. #  出栈函数

  225. function pop(arr,va,t,u)
  226. {
  227.   u=0;
  228.   for(t in arr)
  229.     {
  230.       u++;
  231.     }
  232.   va=arr[u-1];
  233.   delete arr[u-1];
  234.   return va;
  235. }
复制代码

[ 本帖最后由 dbcat 于 2006-4-25 11:08 编辑 ]

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
发表于 2006-04-14 16:03 |显示全部楼层
来个马后炮

  1. [waker@proxy ~]$ echo "1+2*3
  2. 4/6
  3. 2^3+5*6"|
  4. awk '{a=$0;cmd="awk \047BEGIN{print "$0" }\047";cmd|getline ;print a"="$0}'

  5. 1+2*3=7
  6. 4/6=0.666667
  7. 2^3+5*6=38
复制代码

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
发表于 2006-04-14 16:06 |显示全部楼层
忘记及时回收垃圾了

  1. awk '{a=$0;cmd="awk \047BEGIN{print "$0" }\047";cmd|getline ;close(cmd);print a"="$0}'
复制代码

论坛徽章:
0
发表于 2006-04-14 16:51 |显示全部楼层
waker真棒!
用getline实现awk自身调用,这应该是最简单的办法了!

论坛徽章:
0
发表于 2006-04-18 19:00 |显示全部楼层
复杂的程序,我觉得用C/C++实现更好,用python或者php(CLI模式)也可以,如果你喜欢perl还可以用perl,不过我不太喜欢。毕竟shell,awk都不是一个全功能的语言,解决复杂问题比较费劲

论坛徽章:
0
发表于 2006-04-19 11:57 |显示全部楼层
真是精华啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP