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

[数值计算] 批处理版逆波兰四则计算器

[复制链接]
发表于 2019-11-5 22:19:53 | 显示全部楼层 |阅读模式
本帖最后由 老刘1号 于 2020-4-10 21:42 编辑
特点:计算精确无误差。
例:(3*3*3/2)/((-9)/(11111*3*(1-99998/99999)))
VBS计算结果:-.499999999998098
该程序计算结果:-1/2

逆波兰四则计算器.bat
  1. @Echo Off
  2. Setlocal Enabledelayedexpansion
  3. ::CODER BY 老刘 POWERD BY iBAT
  4. Title 【老刘编写】逆波兰四则计算器
  5. Path "%~dp0"
  6. If Not Exist "Stack_LSS.Bat" (
  7.         Echo "Stack_LSS"缺失!
  8.         Pause&Exit
  9. )

  10. Set "Stack=Call Stack_LSS"
  11. !Stack! :Init 运算符
  12. !Stack! :Init 操作数
  13. Echo Code By OldLiu
  14. Echo.
  15. Echo 表达式中只能出现“0123456789+-*/()”这些字符。
  16. Echo 计算支持分数、括号可以嵌套。
  17. Echo 支持负数,但负号前有运算符时需加括号。
  18. Echo 错误举例:6/-3 5--3*-8
  19. Echo 正确举例:6/(-3) 5-(-3*(-8))
  20. Echo 输入Quit或Exit退出。
  21. Echo.
  22. Set /p IsDebug=是否开启DEBUG模式(y/n):
  23. If /i "!IsDebug!" Neq "y" (
  24.         Set "Hide=Rem"
  25. ) Else (
  26.         Set "Hide="
  27. )

  28. :Loop
  29.         Echo. & Set /p "中缀表达式=键入表达式>>> "
  30.         If /i "!中缀表达式!" Equ "Quit" Exit
  31.         If /i "!中缀表达式!" Equ "Exit" Exit
  32.        
  33.         Rem 中缀转后缀。
  34.         !Stack! :Clear 运算符
  35.         Set 后缀表达式=
  36.         Set 可能出现负数=True
  37.         :读取中缀表达式
  38.         If "!中缀表达式!" == "" Goto 中缀转后缀完成
  39.         Set "字符=!中缀表达式:~,1!"
  40.         %Hide% Set 中缀表达式
  41.         Set "中缀表达式=!中缀表达式:~1!"
  42.        
  43.         Rem 处理数字。
  44.         Set /A "IsNum=!字符!" 2>Nul
  45.         If "!IsNum!" EQU "!字符!" (
  46.                 Set 数字=!数字!!字符!
  47.                 Set 可能出现负数=False
  48.                 Goto 读取中缀表达式
  49.         ) Else (
  50.                 If Defined 数字 (
  51.                         Set "后缀表达式=!后缀表达式! !数字!"
  52.                         %Hide% Set 后缀表达式
  53.                         Set 数字=
  54.                 )
  55.         )
  56.        
  57.         Rem 处理左括弧。
  58.         If "!字符!" == "(" (
  59.                 Rem 左括弧不在栈中时优先级最高,直接压栈。
  60.                 !Stack! :Push 运算符 字符
  61.                 Set 可能出现负数=True
  62.                 Goto 读取中缀表达式
  63.         )

  64.         Rem 处理右括弧。
  65.         If "!字符!" == ")" (
  66.                 Rem 运算符出栈,直到遇到左括弧。
  67.                 :括弧中运算符输出
  68.                 !Stack! :Pop 运算符 栈顶运算符
  69.                 If "!栈顶运算符!" Neq "(" (
  70.                         Set "后缀表达式=!后缀表达式! !栈顶运算符!"
  71.                         %Hide% Set 后缀表达式
  72.                         Goto 括弧中运算符输出
  73.                 )
  74.                 Goto 读取中缀表达式
  75.         )
  76.        
  77.         Rem 处理运算符。
  78.         If "!字符!" == "-" (
  79.                 If !可能出现负数! == True (
  80.                         Rem “-”号前面没数字,补一个“0”避免后缀表达式运算错误。
  81.                         Set "后缀表达式=!后缀表达式! 0"
  82.                         %Hide% Set 后缀表达式
  83.                 )
  84.         )
  85.         !Stack! :IsEmpty 运算符
  86.         If !ErrorLevel! Equ 0 (
  87.                 Rem 栈是空的,任何运算符优先级高于空栈,入栈。
  88.                 !Stack! :Push 运算符 字符
  89.                 Goto 读取中缀表达式
  90.         ) Else (
  91.                 :运算符优先级比对
  92.                 !Stack! :Pop 运算符 栈顶运算符
  93.                 If !ErrorLevel! Equ 0 (
  94.                         Set 优先级高=False
  95.                         Rem 一切运算优先级高于栈中的左括弧。
  96.                         If "!栈顶运算符!" == "(" Set 优先级高=True
  97.                         Rem 乘除法优先级高于加减法。
  98.                         If "!栈顶运算符!" == "+" (
  99.                                 If "!字符!" == "*" Set 优先级高=True
  100.                                 If "!字符!" == "/" Set 优先级高=True
  101.                         )
  102.                         If "!栈顶运算符!" == "-" (
  103.                                 If "!字符!" == "*" Set 优先级高=True
  104.                                 If "!字符!" == "/" Set 优先级高=True
  105.                         )
  106.                         If "!优先级高!" == "True" (
  107.                                 Rem 当前运算优先级高于栈顶运算优先级,入栈。
  108.                                 !Stack! :Push 运算符 栈顶运算符
  109.                                 !Stack! :Push 运算符 字符
  110.                                 Goto 读取中缀表达式
  111.                         ) Else (
  112.                                 Rem 当前运算优先级不高于栈顶运算优先级,栈顶的运算可以计算了。
  113.                                 Set "后缀表达式=!后缀表达式! !栈顶运算符!"
  114.                                 %Hide% Set 后缀表达式
  115.                                 Rem 继续出栈,直到栈空或当前运算优先级高于栈顶运算。
  116.                                 Goto 运算符优先级比对
  117.                         )
  118.                 ) Else (
  119.                         Rem 栈已经清空,任何运算符优先级高于空栈,入栈。
  120.                         !Stack! :Push 运算符 字符
  121.                         Goto 读取中缀表达式
  122.                 )
  123.                 Echo 输入的表达式有误。
  124.                 Goto Loop
  125.         )
  126.        
  127.         :中缀转后缀完成
  128.         Rem 写入最后一个数字。
  129.         Set "后缀表达式=!后缀表达式! !数字!"
  130.         Set 数字=
  131.         Rem 弹出栈中所有运算符。
  132.         !Stack! :Pop 运算符 栈顶运算符
  133.         :运算符弹出
  134.                 Set "后缀表达式=!后缀表达式! !栈顶运算符!"
  135.                 !Stack! :Pop 运算符 栈顶运算符
  136.         If !ErrorLevel! Equ 0 Goto 运算符弹出
  137.         %Hide% Set 后缀表达式
  138.        
  139.         Rem 开始计算结果。
  140.         !Stack! :Clear 操作数
  141.         Call :计算结果 !后缀表达式!
  142.         Goto 计算完成
  143.         :计算结果
  144.                 Set 字符=%1
  145.                 Set /A "IsNum=!字符!" 2>Nul
  146.                 If "!IsNum!" EQU "!字符!" (
  147.                         Rem 数字入栈。
  148.                         !Stack! :Push 操作数 字符
  149.                 ) Else (
  150.                         Rem 遇到运算符,计算。
  151.                         Rem 从栈中弹出操作数,注意操作数2先出来。
  152.                         !Stack! :Pop 操作数 操作数2
  153.                         If !ErrorLevel! Neq 0 (
  154.                                 Echo 输入的表达式有误。
  155.                                 Goto Loop
  156.                         )
  157.                         !Stack! :Pop 操作数 操作数1
  158.                         If !ErrorLevel! Neq 0 (
  159.                                 Echo 输入的表达式有误。
  160.                                 Goto Loop
  161.                         )
  162.                         Rem 整数转为分数。
  163.                         If "!操作数1:/=!" Equ "!操作数1!" (
  164.                                 Set "操作数1=!操作数1!/1"
  165.                         )
  166.                         If "!操作数2:/=!" Equ "!操作数2!" (
  167.                                 Set "操作数2=!操作数2!/1"
  168.                         )
  169.                         Rem 进行运算。
  170.                         If "!字符!" Equ "*" (
  171.                                 Rem 分子互乘、分母互乘。
  172.                                 For /f "tokens=1,2 delims=/" %%a in ("!操作数1!") do (
  173.                                         Set /A 当前结果分子=%%a
  174.                                         Set /A 当前结果分母=%%b
  175.                                 )
  176.                                 For /f "tokens=1,2 delims=/" %%a in ("!操作数2!") do (
  177.                                         Set /A 当前结果分子*=%%a
  178.                                         Set /A 当前结果分母*=%%b
  179.                                 )
  180.                         )
  181.                         If "!字符!" Equ "/" (
  182.                                 Rem 除以一个数等于乘其倒数。
  183.                                 For /f "tokens=1,2 delims=/" %%a in ("!操作数1!") do (
  184.                                         Set /A 当前结果分子=%%a
  185.                                         Set /A 当前结果分母=%%b
  186.                                 )
  187.                                 For /f "tokens=1,2 delims=/" %%a in ("!操作数2!") do (
  188.                                         Set /A 当前结果分子*=%%b
  189.                                         Set /A 当前结果分母*=%%a
  190.                                 )
  191.                         )
  192.                         Set 加减法=False
  193.                         If "!字符!" Equ "+" Set 加减法=True
  194.                         If "!字符!" Equ "-" Set 加减法=True
  195.                         If "!加减法!" Equ "True" (
  196.                                 Rem 母互乘子,并以为实,母相乘为法,实如法而一。
  197.                                 For /f "tokens=1,2 delims=/" %%a in ("!操作数1!") do (
  198.                                         Set /A 当前结果分子=%%a
  199.                                         Set /A 当前结果分母=%%b
  200.                                 )
  201.                                 For /f "tokens=1,2 delims=/" %%a in ("!操作数2!") do (
  202.                                         Set /A 当前结果分子=当前结果分子*%%b!字符!当前结果分母*%%a
  203.                                         Set /A 当前结果分母*=%%b
  204.                                 )
  205.                         )
  206.                         Rem 分数化简。
  207.                         Set /A 被除数=当前结果分子,除数=当前结果分母
  208.                         :求最大公约数
  209.                                 If !除数! Equ 0 (
  210.                                         Echo 除以0错误。
  211.                                         Goto Loop
  212.                                 )
  213.                                 Set /A 余数=被除数%%除数
  214.                         If !余数! Neq 0 (
  215.                                 Set /A 被除数=除数,除数=余数
  216.                                 Goto 求最大公约数
  217.                         )
  218.                         Rem 结果约分。
  219.                         Set /A 当前结果分子/=除数,当前结果分母/=除数
  220.                         Set 当前结果=!当前结果分子!/!当前结果分母!
  221.                         %Hide% Echo ^(!操作数1!^)!字符!^(!操作数2!^)=!当前结果!
  222.                         !Stack! :Push 操作数 当前结果
  223.                 )
  224.                 Shift /1
  225.                 If "%1" Neq "" Goto 计算结果
  226.         Goto :Eof
  227.        
  228.         :计算完成
  229.         !Stack! :Pop 操作数 计算结果
  230.         For /f "tokens=1,2 delims=/" %%a in ("!计算结果!") do (
  231.                 Set /A 结果分子=%%a,结果分母=%%b
  232.                 If !结果分母! Lss 0 Set /A 结果分子*=-1,结果分母*=-1
  233.                 If !结果分子! Equ 0 (
  234.                         Echo 结果:0
  235.                 ) Else If !结果分母! Equ 1 (
  236.                         Rem 结果为非0整数。
  237.                         Echo 结果:!结果分子!
  238.                 ) Else If !结果分子! Gtr !结果分母! (
  239.                         Rem 结果大于1。
  240.                         Set /A 商=结果分子/结果分母,余数=%%a%%结果分母
  241.                         Echo 结果:!结果分子!/!结果分母!=!商!…!余数!
  242.                 ) Else (
  243.                         Rem 结果小于1。
  244.                         Echo 结果:!结果分子!/!结果分母!
  245.                 )
  246.         )
  247. Goto Loop
复制代码
Stack_LSS.BAT
计算测试(DEBUG模式开)
  1. 键入表达式>>> (3*3*3/2)/((-9)/(11111*3*(1-99998/99999)))
  2. 中缀表达式=(3*3*3/2)/((-9)/(11111*3*(1-99998/99999)))
  3. 中缀表达式=3*3*3/2)/((-9)/(11111*3*(1-99998/99999)))
  4. 中缀表达式=*3*3/2)/((-9)/(11111*3*(1-99998/99999)))
  5. 后缀表达式= 3
  6. 中缀表达式=3*3/2)/((-9)/(11111*3*(1-99998/99999)))
  7. 中缀表达式=*3/2)/((-9)/(11111*3*(1-99998/99999)))
  8. 后缀表达式= 3 3
  9. 后缀表达式= 3 3 *
  10. 中缀表达式=3/2)/((-9)/(11111*3*(1-99998/99999)))
  11. 中缀表达式=/2)/((-9)/(11111*3*(1-99998/99999)))
  12. 后缀表达式= 3 3 * 3
  13. 后缀表达式= 3 3 * 3 *
  14. 中缀表达式=2)/((-9)/(11111*3*(1-99998/99999)))
  15. 中缀表达式=)/((-9)/(11111*3*(1-99998/99999)))
  16. 后缀表达式= 3 3 * 3 * 2
  17. 后缀表达式= 3 3 * 3 * 2 /
  18. 中缀表达式=/((-9)/(11111*3*(1-99998/99999)))
  19. 中缀表达式=((-9)/(11111*3*(1-99998/99999)))
  20. 中缀表达式=(-9)/(11111*3*(1-99998/99999)))
  21. 中缀表达式=-9)/(11111*3*(1-99998/99999)))
  22. 后缀表达式= 3 3 * 3 * 2 / 0
  23. 中缀表达式=9)/(11111*3*(1-99998/99999)))
  24. 中缀表达式=)/(11111*3*(1-99998/99999)))
  25. 后缀表达式= 3 3 * 3 * 2 / 0 9
  26. 后缀表达式= 3 3 * 3 * 2 / 0 9 -
  27. 中缀表达式=/(11111*3*(1-99998/99999)))
  28. 中缀表达式=(11111*3*(1-99998/99999)))
  29. 中缀表达式=11111*3*(1-99998/99999)))
  30. 中缀表达式=1111*3*(1-99998/99999)))
  31. 中缀表达式=111*3*(1-99998/99999)))
  32. 中缀表达式=11*3*(1-99998/99999)))
  33. 中缀表达式=1*3*(1-99998/99999)))
  34. 中缀表达式=*3*(1-99998/99999)))
  35. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111
  36. 中缀表达式=3*(1-99998/99999)))
  37. 中缀表达式=*(1-99998/99999)))
  38. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3
  39. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 *
  40. 中缀表达式=(1-99998/99999)))
  41. 中缀表达式=1-99998/99999)))
  42. 中缀表达式=-99998/99999)))
  43. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 * 1
  44. 中缀表达式=99998/99999)))
  45. 中缀表达式=9998/99999)))
  46. 中缀表达式=998/99999)))
  47. 中缀表达式=98/99999)))
  48. 中缀表达式=8/99999)))
  49. 中缀表达式=/99999)))
  50. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 * 1 99998
  51. 中缀表达式=99999)))
  52. 中缀表达式=9999)))
  53. 中缀表达式=999)))
  54. 中缀表达式=99)))
  55. 中缀表达式=9)))
  56. 中缀表达式=)))
  57. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 * 1 99998 99999
  58. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 * 1 99998 99999 /
  59. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 * 1 99998 99999 / -
  60. 中缀表达式=))
  61. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 * 1 99998 99999 / - *
  62. 中缀表达式=)
  63. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 * 1 99998 99999 / - * /
  64. 后缀表达式= 3 3 * 3 * 2 / 0 9 - 11111 3 * 1 99998 99999 / - * /  /
  65. (3/1)*(3/1)=9/1
  66. (9/1)*(3/1)=27/1
  67. (27/1)/(2/1)=27/2
  68. (0/1)-(9/1)=-9/1
  69. (11111/1)*(3/1)=33333/1
  70. (99998/1)/(99999/1)=99998/99999
  71. (1/1)-(99998/99999)=1/99999
  72. (33333/1)*(1/99999)=1/3
  73. (-9/1)/(1/3)=-27/1
  74. (27/2)/(-27/1)=1/-2
  75. 结果:-1/2
复制代码

评分

参与人数 1技术 +1 收起 理由
523066680 + 1 厉害

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-3-16 20:18 , Processed in 0.019282 second(s), 7 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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