找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 16230|回复: 9

逆波兰计算器 revpolish 3.0版

[复制链接]
发表于 2017-1-2 23:15:03 | 显示全部楼层 |阅读模式
本帖最后由 happy886rr 于 2017-1-28 15:21 编辑

[version 3.0]  2017-01-28,更新只更新源码,而不做下载更新,请编译源码获取最新版。
逆波兰计算器revpolish 3.0版,支持复杂多函数混合嵌套。恐怖的计算速度,四则运算每秒可以处理1000万行,复杂数学函数嵌套,每秒可处理200万行。支持最全面的数学函数,支持超长算式,可以自定义#define  STACK_SIZE 的值,理论上不限制算式长度。拥有详细的错误反馈,无论是除数为0,还是负数开方,都会立刻终止程序并打印错误信息。跳转排序亦根据使用频率设定,使其以最小的内存、cpu占用、最快的速度完成艰巨的科学计算。

revpolish采取多版本发行策略,请下载支持您设备的版本。
摘要:
x86&x64架构windows版, 下载:revpolish.exe


x86&x64架构linux版, 下载: revpolish


安卓apk 版, 下载: revpolish.apk


arm架构版, 下载: revpolish

用法:
-----------------------------------------------------------------------------
revpolish [expression]
-----------------------------------------------------------------------------

示例:
-----------------------------------------------------------------------------
    revpolish ((3*3+2)%6+7.187)*5-7/189+3^2
    revpolish (ceil(sin(pi/3)+2)%6+0.187)*e-lg(6.5)
    revpolish 5*(arctan(cos(sin(ln(lg(2.71828))))))
-----------------------------------------------------------------------------

备注:
-----------------------------------------------------------------------------
常数类
        pi    3.1415926535897932
        e     2.7182818284590452
通用类
        rand  随机数
        round 四舍五入
        int   取整
        ceil  向上舍入
        floor 向下舍入
        abs   绝对值
        sqrt  开方
        lg    常用对数,以10为底
        ln    自然对数
        exp   e的次幂
        gamma 伽玛函数
        deg   度转弧度
        +     加
        -     减
        *     乘
        /     除
        %     取余数
        ^     次方
        !     阶乘
三角函数类
        sin、cos、tan   
        arcsin、arccos、arctan
双曲函数类
        sinh、cosh、tanh
        arcsinh、arccosh、arctanh
-----------------------------------------------------------------------------


revpolish.c   3.0版本源码

  1. /*
  2.     REVERSE POLISH EXPRESSION CALCULATOR, COPYRIGHT@2017~2019 BY HAPPYSXYF
  3.     REVPOLISH.EXE
  4.     VERSION 3.0
  5. */

  6. #include   <stdio.h>
  7. #include  <stdlib.h>
  8. #include    <math.h>

  9. /***************定义宏变量***************/
  10. //堆栈尺寸
  11. #define  STACK_SIZE   1024
  12. //帮助说明
  13. #define HELPINFORMATION "\
  14. REVERSE POLISH EXPRESSION CALCULATOR,COPYRIGHT@2017~2019 BY HAPPY\n\
  15. -----------------------------------------------------------------\n\
  16. revpolish [expression]\n\
  17. -----------------------------------------------------------------\n\
  18. FUNCTIONS:\n\
  19.     pi=3.1415926535897932, e=2.7182818284590452\n\
  20.     +, -, *, /, %, ^, !\n\
  21.     round, floor, ceil, exp, deg, sqrt, abs, lg, ln\n\
  22.     sin, cos, tan, arcsin, arccos, arctan\n\
  23.     sinh, cosh, tanh, arcsinh, arccosh, arctanh\n\
  24. -----------------------------------------------------------------\n\
  25. VERSION 3.0 2017-01-28\n"

  26. /***************全局类变量***************/
  27. //数学函数关键词
  28. static const char* KEY_WORDS[]={"e", "pi", "sqrt", "lg", "ln", "sin", "cos", "tan", "arcsin", "arccos", "arctan", "deg", "abs", "round", "floor", "ceil", "exp", "sinh", "cosh", "tanh", "arcsinh", "arccosh", "arctanh", "int", "gamma", "rand", NULL};
  29. //运算符栈
  30. char   STACK1[STACK_SIZE]={0};
  31. //逆波兰栈
  32. char   STACK2[STACK_SIZE]={0};
  33. //浮点数栈
  34. double STACK3[STACK_SIZE]={0};

  35. /***************功能函数类***************/
  36. //阶乘函数
  37. long long fact(long long n)
  38. {
  39.     return (n<2) ?1 :n*(fact(n-1));
  40. }
  41. //逆波兰核心
  42. double RevPolishCore(const char* expression)
  43. {
  44.         char   *op=(char*)expression, *S1=STACK1, *S2=STACK2, **key, *cp, *kp;
  45.         double *S3=STACK3, di, ni;
  46.         int    brackets=0;
  47.         STACK3[0]=0;
  48.        
  49.         //生成逆波兰       
  50.         while(*op!='\0'){               
  51.                 switch(*op){
  52.                 case ' ' :
  53.                 case '\t':
  54.                 case '\r':
  55.                 case '\n':
  56.                         //过滤空字符
  57.                         op++;
  58.                         continue;

  59.                 case 'a':
  60.                 case 'b':
  61.                 case 'c':
  62.                 case 'd':
  63.                 case 'e':
  64.                 case 'f':
  65.                 case 'g':
  66.                 case 'h':
  67.                 case 'i':
  68.                 case 'j':
  69.                 case 'k':
  70.                 case 'l':
  71.                 case 'm':
  72.                 case 'n':
  73.                 case 'o':
  74.                 case 'p':
  75.                 case 'q':
  76.                 case 'r':
  77.                 case 's':
  78.                 case 't':
  79.                 case 'u':
  80.                 case 'v':
  81.                 case 'w':
  82.                 case 'x':
  83.                 case 'y':
  84.                 case 'z':
  85.                         //识别数学函数关键词
  86.                         key=(char**)KEY_WORDS;
  87.                         while(*key !=NULL){       
  88.                                 cp=op, kp=*key;
  89.                                 //比对关键词字母
  90.                                 while(*cp==*kp && *kp!='\0'){
  91.                                         cp++, kp++;
  92.                                 }
  93.                                 //验证关键词结尾
  94.                                  if((*cp<'a'||*cp>'z') && (*kp=='\0')){
  95.                                          op=cp;
  96.                                         break;
  97.                                 }
  98.                                 key++;
  99.                         }
  100.                         //构建伪双目
  101.                         if(*key !=NULL){                               
  102.                                 *(S2++)='.';
  103.                                 *(S2++)=' ';
  104.                                 //伪双目入栈
  105.                                 while('A'<=(*S1) && (*S1)<='Z'){
  106.                                         *(S2++)=*(S1--);
  107.                                 }
  108.                                 *(++S1)=key-(char**)KEY_WORDS+65;
  109.                                 continue;
  110.                         }else{
  111.                                 //无法识别的数学函数
  112.                                 fputs("Unrecognized math function\n", stderr);
  113.                                 exit(1);
  114.                         }
  115.                         break;
  116.                
  117.                 case '(':
  118.                         brackets++;
  119.                         *(++S1)=*op;
  120.                         if(*(op+1)=='-' || *(op+1)=='+'){
  121.                                 *(S2++)='0', *(S2++)=' ';
  122.                         }
  123.                         break;

  124.                 case ')':
  125.                         brackets--;
  126.                         while(*S1!='(')
  127.                         {
  128.                                 *(S2++)=*(S1--);
  129.                         }               
  130.                         //舍弃'('
  131.                         S1--;               
  132.                         break;

  133.                 case '+':
  134.                 case '-':
  135.                         while(S1!=STACK1 && *S1!='(')
  136.                         {
  137.                                 *(S2++)=*(S1--);
  138.                         }
  139.                         *(++S1)=*op;
  140.                         break;

  141.                 case '^':
  142.                         //指数符
  143.                         while('A'<=(*S1) && (*S1)<='Z')
  144.                         {
  145.                                 *(S2++)=*(S1--);
  146.                         }
  147.                         *(++S1)=*op;
  148.                         break;

  149.                 case '!':
  150.                         //阶乘符
  151.                         *(S2++)=*op;
  152.                         break;

  153.                 case '%':
  154.                 case '*':
  155.                 case '/':
  156.                         while(('A'<=(*S1) && (*S1)<='Z') ||*S1=='%' ||*S1=='*' ||*S1=='/' ||*S1=='^'){
  157.                                 *(S2++)=*(S1--);
  158.                         }
  159.                         *(++S1)=*op;
  160.                         break;

  161.                 default :
  162.                         if((*op<'0' || *op>'9') && (*op!='.')){
  163.                                 //无法识别的运算符
  164.                                 fputs("Unrecognized operator\n", stderr);
  165.                                 exit(1);
  166.                         }
  167.                         //浮点数入栈
  168.                         while(('0'<=*op && *op<='9') ||*op=='.'){
  169.                                 *(S2++)=*(op++);
  170.                         }
  171.                         op--;
  172.                         *(S2++)=' ';
  173.                         break;
  174.                 }
  175.                 op++;
  176.         }

  177.         //验证括号是否闭合
  178.         if(brackets){
  179.                 fputs("The brackets '(' or ')' are not closed", stderr);
  180.                 exit(1);
  181.         }

  182.         //收尾逆波兰
  183.         while(S1 !=STACK1){*(S2++)=*(S1--);}
  184.         *S2=' ';

  185.         //计算逆波兰
  186.         op=STACK2;
  187.         while(*op!=' '){
  188.                 switch(*op){
  189.                 case 'A':
  190.                         *S3=2.7182818284590452;
  191.                         break;
  192.                 case 'B':
  193.                         *S3=3.1415926535897932;
  194.                         break;
  195.                 case 'C':
  196.                         if(*S3 <0){
  197.                                 //负数没有平方根
  198.                                 fputs("Negative numbers have no square root\n", stderr);
  199.                                 exit(1);
  200.                         }
  201.                         *(S3-1)=sqrt(*S3);
  202.                         S3--;
  203.                         break;
  204.                 case 'D':
  205.                         if(*S3 <0){
  206.                                 //负数没有对数
  207.                                 fputs("Negative numbers are not logarithmic\n", stderr);
  208.                                 exit(1);
  209.                         }
  210.                         *(S3-1)=log10(*S3);
  211.                         S3--;
  212.                         break;
  213.                 case 'E':
  214.                         if(*S3 <0){
  215.                                 //负数没有自然对数
  216.                                 fputs("Negative numbers have no natural logarithms\n", stderr);
  217.                                 exit(1);
  218.                         }
  219.                         *(S3-1)=log(*S3);
  220.                         S3--;
  221.                         break;
  222.                 case 'F':
  223.                         *(S3-1)=sin(*S3);
  224.                         S3--;
  225.                         break;
  226.                 case 'G':
  227.                         *(S3-1)=cos(*S3);
  228.                         S3--;
  229.                         break;
  230.                 case 'H':
  231.                         if(*S3==3.1415926535897932/2){
  232.                                 //π/2没有正切值
  233.                                 fputs("The pi/2 has no tangent\n", stderr);
  234.                                 exit(1);
  235.                         }
  236.                         *(S3-1)=tan(*S3);
  237.                         S3--;
  238.                         break;
  239.                 case 'I':
  240.                         *(S3-1)=asin(*S3);
  241.                         S3--;
  242.                         break;
  243.                 case 'J':
  244.                         *(S3-1)=acos(*S3);
  245.                         S3--;
  246.                         break;
  247.                 case 'K':
  248.                         *(S3-1)=atan(*S3);
  249.                         S3--;
  250.                         break;
  251.                 case 'L':
  252.                         *(S3-1)=(*S3)*3.1415926535897932/180.0;
  253.                         S3--;
  254.                         break;
  255.                 case 'M':
  256.                         *(S3-1)=fabs(*S3);
  257.                         S3--;
  258.                         break;
  259.                 case 'N':
  260.                         *(S3-1)=round(*S3);
  261.                         S3--;
  262.                         break;
  263.                 case 'O':
  264.                         *(S3-1)=floor(*S3);
  265.                         S3--;
  266.                         break;
  267.                 case 'P':
  268.                         *(S3-1)=ceil(*S3);
  269.                         S3--;
  270.                         break;
  271.                 case 'Q':
  272.                         *(S3-1)=exp(*S3);
  273.                         S3--;
  274.                         break;
  275.                 case 'R':
  276.                         *(S3-1)=sinh(*S3);
  277.                         S3--;
  278.                         break;
  279.                 case 'S':
  280.                         *(S3-1)=cosh(*S3);
  281.                         S3--;
  282.                         break;
  283.                 case 'T':
  284.                         *(S3-1)=tanh(*S3);
  285.                         S3--;
  286.                         break;
  287.                 case 'U':
  288.                         *(S3-1)=asinh(*S3);
  289.                         S3--;
  290.                         break;
  291.                 case 'V':
  292.                         *(S3-1)=acosh(*S3);
  293.                         S3--;
  294.                         break;
  295.                 case 'W':
  296.                         *(S3-1)=atanh(*S3);
  297.                         S3--;
  298.                         break;
  299.                 case 'X':
  300.                         *(S3-1)=(int)(*S3);
  301.                         S3--;
  302.                         break;
  303.                 case 'Y':
  304.                         if(*S3 <0){
  305.                                 //负数没有伽玛函数
  306.                                 fputs("Negative numbers have no factorial", stderr);
  307.                                 exit(1);
  308.                         }
  309.                         *(S3-1)=tgamma((*S3)+1);
  310.                         S3--;
  311.                         break;
  312.                 case 'Z':
  313.                         //随机数生成器
  314.                         if(*S3 <0){
  315.                                 //负数没有伽玛函数
  316.                                 fputs("A negative number can not be used as a random upper bound", stderr);
  317.                                 exit(1);
  318.                         }else if(*S3 <2){
  319.                                 //负数没有伽玛函数
  320.                                 *(S3-1)=rand() % 8192 /8192.0;
  321.                         }else{
  322.                                 *(S3-1)=rand() % (int)(*S3);
  323.                         }
  324.                         S3--;
  325.                         break;
  326.                 case '+':
  327.                         *(S3-1)+=*S3;
  328.                         S3--;
  329.                         break;
  330.                 case '-':
  331.                         *(S3-1)-=*S3;
  332.                         S3--;
  333.                         break;
  334.                 case '*':
  335.                         *(S3-1)*=*S3;
  336.                         S3--;
  337.                         break;
  338.                 case '%':
  339.                 case '/':
  340.                         if(*S3 !=0){
  341.                                 if(*op=='%'){
  342.                                         //取余数
  343.                                         *(S3-1)=(int)*(S3-1) % (int)*S3;
  344.                                 }else{
  345.                                         *(S3-1)/=*S3;
  346.                                 }
  347.                                
  348.                         }else{
  349.                                 //除数不能为零
  350.                                 fputs("Divisor is zero error\n", stderr);
  351.                                 exit(1);
  352.                         }
  353.                         S3--;
  354.                         break;
  355.                 case '^':
  356.                         if(*(S3-1)==0 && *S3<0){
  357.                                 //除数不能为零
  358.                                 fputs("Function pow's divisor is zero error\n", stderr);
  359.                                 exit(1);
  360.                         }
  361.                         *(S3-1)=pow(*(S3-1), *S3);
  362.                         S3--;
  363.                         break;
  364.                 case '!':
  365.                         if(*S3 <0){
  366.                                 //负数没有阶乘
  367.                                 fputs("Negative numbers have no factorial\n", stderr);
  368.                                 exit(1);
  369.                         }
  370.                         *S3=fact((long long)(*S3));
  371.                         break;
  372.                 default :
  373.                         //字符串转浮点
  374.                         di=0, ni=1;
  375.                         while('0'<=*op && *op<='9'){
  376.                                 di=10*di+(*op)-'0';
  377.                                 op++;
  378.                         }       
  379.                         if(*op=='.'){
  380.                                 op++;
  381.                                 while('0'<=*op && *op<='9'){
  382.                                         di=10*di+(*op)-'0';
  383.                                         op++, ni*=10;
  384.                                 }       
  385.                         }
  386.                         *(++S3)=di/ni;
  387.                         break;
  388.                 }
  389.                 op++;
  390.         }

  391.         //判断结果是否异常或溢出
  392.         if(isinf(*S3)||isnan(*S3)){
  393.                 fputs("Overflow or illegal operation is calculated", stderr);
  394.                 exit(1);
  395.         }

  396.         /////////////////////////////////////////////////////////////////////
  397.         //返回计算结果
  398.         //return *S3;

  399.         //打印中缀式
  400.         fprintf(stdout, "ORIGINALEXP: %s\n", expression);

  401.         //打印后缀式
  402.         fprintf(stdout, "REVPOLISH:   ");
  403.         op=STACK2;
  404.         while(op!=S2){
  405.                 if(*op=='.' && *(op+1)==' '){
  406.                         op++;

  407.                 }else if('A'<=(*op) && (*op)<='Z'){
  408.                         fprintf(stdout, "%s ", KEY_WORDS[*op-65]);
  409.                        
  410.                 }else{
  411.                         fputc(*op, stdout);
  412.                         if(*op=='+' ||*op=='-' ||*op=='*' ||*op=='/' ||*op=='%' ||*op=='^' ||*op=='!'){fputc(' ', stdout);}
  413.                 }
  414.                 op++;
  415.         }
  416.         fputc('\n', stdout);

  417.         //打印计算结果
  418.         fprintf(stdout, "RESULT:      %.16lf\n", *S3);
  419. }

  420. /*************MAIN主函数入口*************/
  421. int main(int argc, char** argv)
  422. {
  423.         if((argc==1) || (argc==2 && argv[1][0]=='/' && (argv[1][1]=='?'||argv[1][1]=='h'))){
  424.                 //使用说明
  425.                 fputs(HELPINFORMATION, stderr);
  426.                 exit(1);
  427.         }
  428.         //初始化随机种子
  429.         srand((int)getpid());
  430.         RevPolishCore(argv[1]);
  431.         return 0;
  432. }
复制代码
gcc编译参数
  1. gcc revpolish.c -std=gnu99 -O3 -s -o revpolish.exe
复制代码
cmd调用示例
  1. @echo off
  2. ::****************************************************
  3. :HEAD
  4. revpolish
  5. ping -n 2 127.1>NUL
  6. echo;
  7. echo;

  8. ::****************************************************
  9. :TEST
  10. for /f "delims=" %%a in ('more +16 "%~f0"') do (
  11.         revpolish "%%a"&echo;
  12. )
  13. set/p=Well Done!&exit

  14. ::****************************************************
  15. abs(1/(2*50)*lg(2*pi*(e^2)/(2*50+1))-lg2)
  16. ((((((((2^2)*2)^2)*2)^2)*2)^2)^2)*2
  17. -((((((((2^2)*2)^2)*2)^2)*2)^2)^2)*2
  18. 23+56/(102-100)*((36-24)/(8-6))
  19. sin(6)+3
  20. cos(sin(6)^4)^6
  21. cos(sin(-6)^4)^6
  22. cos(-sin(6)^4)^6
  23. 2^cos(sin(6)^4)^6
  24. 2^sin(3)^2
  25. 4^4!
  26. 3^4^2
  27. gamma(20.3)
复制代码

评分

参与人数 3PB +7 技术 +2 收起 理由
CrLf + 1 棒棒哒!
523066680 + 6 + 1 同支持!
莫奈良 + 1 真的是黑科技 虽然看不懂 还是要支持一下了

查看全部评分

发表于 2017-1-6 21:16:31 | 显示全部楼层
真的是黑科技 虽然看不懂 还是要支持一下了
发表于 2017-1-6 23:36:56 | 显示全部楼层
名字略怪,还以为是计算逆波兰式的,结果其实是波兰式
 楼主| 发表于 2017-1-7 11:14:39 | 显示全部楼层
回复 3# CrLf
回复大师,这版主要是优化速度,所以没用数据结构的pop、push,而是用全局静态数组实现的。其中atof也改用自己的实现,所以比调用atof速度要快,核心不调用任何函数,单目、双目全部用双目实现。
发表于 2017-1-7 23:55:22 | 显示全部楼层
linux下编译环境的应该是比较好弄。
windows 下有条件和能力的估计不多。
所以exe还是有必要发布一下。
发表于 2017-1-8 00:04:46 | 显示全部楼层
回复 5# codegay


    gcc 可以直接编译,但是 gcc 有一个问题,会将带通配符的参数展开为路径,而这个行为是编译器主动进行的,所以我都尽量用 tcc 编译
    无奈的是 tcc 的库太少,编译起来实在不方便
 楼主| 发表于 2017-1-8 18:42:08 | 显示全部楼层
本帖最后由 happy886rr 于 2017-1-8 18:50 编辑

回复 6# CrLf
大师手机上也能编译,我用c4droid的手机版tcc直接.编译成了apk和arm架构C版本,已更新到顶楼。在手机上的体验很棒,完全取代了自带的计算器,有12位有效精度。
发表于 2017-1-8 20:29:16 | 显示全部楼层
回复 7# happy886rr


    手机有 #include <windows.h> 吗?
 楼主| 发表于 2017-1-8 21:44:09 | 显示全部楼层
回复 8# CrLf
那个windows头我写多余了,其实只要有stdio和math这两个头就足够。代码无需修改支持各种C平台直接编译。我已经在虚拟机里测试了linux版,完全可用。
发表于 2017-2-21 00:51:58 | 显示全部楼层
本帖最后由 pighead123 于 2017-2-21 00:56 编辑

很好,怎么不放到 github 去?放上去就方便管理和发布了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-16 22:35 , Processed in 0.022753 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表