免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2919 | 回复: 8
打印 上一主题 下一主题

AWK 计算器修订版 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-04-24 11:13 |只看该作者 |倒序浏览
说来有点不好意思,因为过于仓促,上次写的那个AWK求值程序只能支持简单的5种运算,而且还有很多不妥的地方。恰好今天有空,便对那个程序进行了些改进,使之能够支持"sin cos tg ..."等常用函数运算,及"! != < > ..."等逻辑运算。程序的基本原理不变,还是利用栈来进行操作。
   欢迎大家拍砖。



运行方法:

  1. echo '
  2. 1.1+2.3*sin(1.2*exp(3))+2.1^2.1
  3. 1!=2&1|0
  4. PI+E^arctan(1)
  5. ' | awk -f eval
复制代码



程序代码eval:



  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. }


复制代码



另外:
受 WAKER 版主启发 ,写了一个精简版的,运行方法同上:


  1. #! /usr/bin/awk
  2. # GNU Awk 3.1.4
  3. {
  4. eval($0);
  5. }

  6. function eval(cmd,expression)
  7. {
  8.   expression = "awk \047BEGIN{print "cmd" }\047"
  9.   system(expression)
  10. }
复制代码

评分

参与人数 1可用积分 +2 收起 理由
waker + 2

查看全部评分

论坛徽章:
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
2 [报告]
发表于 2006-04-24 11:21 |只看该作者
葱白

论坛徽章:
0
3 [报告]
发表于 2006-04-24 11:24 |只看该作者
有道是,巾帼不让须眉呀!佩服佩服

论坛徽章:
0
4 [报告]
发表于 2006-04-24 11:25 |只看该作者
原帖由 waker 于 2006-4-24 11:21 发表
葱白



表药盲目葱白

论坛徽章:
0
5 [报告]
发表于 2006-04-24 19:50 |只看该作者
呵呵,你这个不能对自定义的函数进行运算吧?
比如evaluate(func())

论坛徽章:
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
6 [报告]
发表于 2006-04-24 19:57 |只看该作者
原帖由 苏蓉蓉 于 2006-4-24 19:50 发表
呵呵,你这个不能对自定义的函数进行运算吧?
比如evaluate(func())

准备忽悠楼主用awk重新实现一遍awk

论坛徽章:
0
7 [报告]
发表于 2006-04-24 20:05 |只看该作者
提一个建议嘛。
wayy2008 该用户已被删除
8 [报告]
发表于 2006-04-24 20:58 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
9 [报告]
发表于 2006-04-25 02:09 |只看该作者
楼主已经中毒非浅了阿,呵呵:)

nix中的 lex、yacc、sed、awk、gperf、grep、sh 用好了感觉非常好,
而且欲罢不能阿。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP