1. java使用双栈实现一个计算器

基本逻辑

  • 双栈分别存储数值(nums)和操作符(ops
  • 在实现时需要注意优先级
    • 如果当前操作符是 ‘)’ 时,需要在遍历过程中把括号内数据做一次计算
    • 如果当前遍历的操作符如果是 + - ,且操作符栈ops的操作符是 * /,则需要优先计算 */的逻辑
  • 上边都做完的话,最终都是简单的 + - 逻辑了,直接计算即可

BigDicemal版本


public class calculatorBigdecimal {public static BigDecimal calculate(String expression) {Stack<BigDecimal> nums = new Stack<>();Stack<Character> ops = new Stack<>();//记录是否需要把 - 作为 负数存储boolean isOperatorPre = false;for (int i = 0; i < expression.length(); i++) {char c = expression.charAt(i);if (Character.isDigit(c)) {int j = i;while (j < expression.length() && (Character.isDigit(expression.charAt(j)) || '.' == expression.charAt(j))) {j++;}isOperatorPre = false;nums.push(new BigDecimal(expression.substring(i, j)));i = j - 1;} else if (c == '(') {isOperatorPre = true;ops.push(c);} else if (c == ')') {while (ops.peek() != '(') {isOperatorPre = false;nums.push(calculateByOps(ops.pop(), nums.pop(), nums.pop()));}ops.pop();} else if (isOperator(c)) {if (c == '-' && (isOperatorPre || ops.empty())) {int j = i + 1;while (j < expression.length() && (Character.isDigit(expression.charAt(j)) || '.' == expression.charAt(j))) {j++;}nums.push(new BigDecimal(expression.substring(i + 1, j)).negate());i = j - 1;isOperatorPre = false;} else {while (!ops.empty() && needCalculatePre(c, ops.peek())) {nums.push(calculateByOps(ops.pop(), nums.pop(), nums.pop()));}isOperatorPre = true;ops.push(c);}}}while (!ops.empty()) {nums.push(calculateByOps(ops.pop(), nums.pop(), nums.pop()));}return nums.pop();}private static boolean isOperator(char c) {return c == '+' || c == '-' || c == '*' || c == '/';}private static boolean needCalculatePre(char op1, char op2) {if (op2 == '(' || op2 == ')') {return false;}return (op2 == '*' || op2 == '/') && (op1 == '+' || op1 == '-') || (op2 == '+' || op2 == '-') && (op1 == '+' || op1 == '-');}private static BigDecimal calculateByOps(char op, BigDecimal b, BigDecimal a) {switch (op) {case '+':return a.add(b);case '-':return a.subtract(b);case '*':return a.multiply(b).setScale(4, BigDecimal.ROUND_HALF_UP);case '/':if (b.compareTo(BigDecimal.ZERO) == 0) {throw new UnsupportedOperationException("Cannot divide by zero");}return a.divide(b, 4, RoundingMode.HALF_UP);default:throw new UnsupportedOperationException("Unknown operator " + op);}}

把一个表达式传入上面的方法即可完成计算
如: (2*5+5)*2-3 = 27

如果再来点难度,把这个表达式的数字依次替换成其他的数值,并完成计算,该怎么做呢?

  1. 依次取到原表达式的数据
  public static List<Long> findNumbers(String expression) {List<Long> numberList = new ArrayList<>();Matcher matcher = Pattern.compile("\\d+").matcher(expression);while (matcher.find()) {Long number = Long.parseLong(matcher.group());numberList.add(number);}return numberList;}
  1. 根据映射关系获取表达式的数据所对应的真实数据
  2. 把真实数据按指定位置替换到表达式中,调用上面的方法完成计算
public static String replaceNumbers(String expression, List<Long> nums, Map<Long, BigDecimal> idAmountMap) {StringBuilder newExpression = new StringBuilder(expression);for (Long id : nums) {BigDecimal amount = idAmountMap.get(id);if (amount == null) {amount = BigDecimal.ZERO;}String numberStr = amount.toString();// 构建数字的正则表达式,确保匹配的数字是一个独立的单词String regex = "(?<![\\d.])" + id + "(?![\\d.])";Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(newExpression);// 逐个查找并替换匹配的数字while (matcher.find()) {int start = matcher.start();int end = matcher.end();newExpression.replace(start, end, numberStr);// 更新偏移量,避免重复替换同一个数字matcher.region(start + numberStr.length(), newExpression.length());}}return newExpression.toString();}

main方法测试:

    public static void main(String[] args) {HashMap<Long, BigDecimal> map = new HashMap<>();map.put(1l, new BigDecimal("100.7563"));map.put(2l, new BigDecimal("200.2131"));map.put(3l, new BigDecimal("300.7908"));map.put(4l, new BigDecimal("400.2128"));map.put(10l, new BigDecimal("1000.4338"));map.put(10000000000l, new BigDecimal("5.0000"));String expressionaaa = "(10000000000-5+5)*2-3";List<Long> numbers = findNumbers(expressionaaa);System.out.println(numbers);String exP = replaceNumbers(expressionaaa, numbers, map);System.out.println(exP);System.out.println();String expression0 = "(-2+-5+5)*2-3";List<Long> numbers0 = findNumbers(expression0);System.out.println(numbers0);String exP0 = replaceNumbers(expression0, numbers0, map);System.out.println(exP0);System.out.println("(2-5+5)*2-3 = " + calculate(exP0));System.out.println();String expression1 = "(-2*5+5)*2-3";List<Long> numbers1 = findNumbers(expression1);System.out.println(numbers1);String exP1 = replaceNumbers(expression1, numbers1, map);System.out.println(exP1);System.out.println("(2*5+5)*2-3 = " + calculate(exP1));System.out.println();String expression2 = "-10+-5*(2-2)";System.out.println("10+5*(2-2) = " + calculate(expression2));String expression3 = "10+5/(4-1)"; //除不尽转化为BigDecimalList<Long> numbers3 = findNumbers(expression3);System.out.println(numbers3);String exP3 = replaceNumbers(expression3, numbers3, map);System.out.println(exP3);System.out.println("10+5/(4-1) = " + calculate(exP3));System.out.println();String expression6 = "2-5+2-3";System.out.println("2-5+2-3 = " + calculate(expression6));}

输出结果

java实现一个计算器:输入计算公式即可输出结果相关推荐

  1. java定义一个方法,向控制台输出一个整数的阶乘

    java定义一个方法,向控制台输出一个整数的阶乘 /*** 定义一个方法,向控制台输出一个整数的阶乘*/ public class Test19 {//输出阶乘的方法public static voi ...

  2. java定义一个方法,向控制台输出99乘法表

    java定义一个方法,向控制台输出99乘法表 /*** 定义一个方法* 向控制台输出99乘法表*/ public class Test18 {public static void main(Strin ...

  3. 实现一个函数输入123456789,输出123,456,789”

    //实现一个函数输入123456789,输出123,456,789"var a=123456789;var b=a.toString().split('');var arr=[];for(v ...

  4. java中double身高_用JAVA编一个程序 输入10名同学的身高,找出最高升高,要求使用对象数组类型的带参方法来实现...

    用JAVA编一个程序 输入10名同学的身高,找出最高升高,要求使用对象数组类型的带参方法来实现 关注:285  答案:5  mip版 解决时间 2021-02-05 07:44 提问者女人不需要倾国倾 ...

  5. 用java实现一个计算器程序_1.2第一个java程序——hello world

    第一个java程序--hello world 实现一个java程序,主要有三个步骤:1.编写源代码,2.编译源代码,3.运行.java的源代码必须先编译,然后才能由JVM解析执行.所以我们程序员第一步 ...

  6. 用java编写一个计算器_用java程序编写一个计算器

    展开全部 给你一个参考,希望不62616964757a686964616fe58685e5aeb931333330343261要被百度吞了当晚餐 import java.awt.BorderLayou ...

  7. java 写一个计算器_java编写一个计算器类

    展开全部 import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; import java.aw ...

  8. 用java编写计算器_用JAVA编写一个计算器

    展开全部 import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; import java.aw ...

  9. java程序a-z_用Java写一个程序:使其输出从A-Z的排序字母

    共回答了24个问题采纳率:79.2% 按照你的要求写的如下代码,精短而高效,可以直接运行 public class Luck { x09public static void main(String[] ...

最新文章

  1. 前端Vue学习之路(五)插件的使用
  2. R语言数据包自带数据集之survival包的colon数据集字段解释、数据导入实战
  3. Science:细胞如何测量自身的大小?答案是:DNA含量
  4. 可用性追踪是虚拟化网络的关键
  5. 傅里叶变换在图像处理中的应用初步学习
  6. 打工人的一把辛酸泪,网站提现为啥多于800要扣20%的税?我想这些东西你需要明白
  7. 手把手教你实现一个 AdaBoost
  8. java数组长度最大值_java 数组排序、最大值、最小值 | 学步园
  9. Apache Camel请向我解释这些端点选项的含义
  10. python分析服务器日志_python实现web服务器日志分析脚本
  11. 作者:董西松,男,博士,现任中国科学院自动化研究所助理研究员。
  12. python2和3安装后怎样切换 mac_Mac下安装配置Python2和Python3并相互切换使用
  13. Redis数据持久化管理之RDB模式
  14. JavaScript进阶高级
  15. redis-hmap --go
  16. 使用Q-Vision软件Kvaser硬件产品,支持ADAS测试,实现对总线网络的分析
  17. 企业借力OA系统打造数字档案馆,提高档案管理、查阅效率
  18. 了解5G技术与未来5G面临的问题
  19. phaser.sprite.body overlap collide seperate
  20. 工作笔记:如何用Django连接Kerberized甲骨文(Oracle)数据库

热门文章

  1. 嵌入式软件开发——嵌入式软件工程师:就职的“门票”
  2. Quartz.Net的简单练习
  3. 企业信息化发展下,适合中小企业的容灾备份解决方案
  4. iPhone和ipad使用itools安装ipa软件
  5. 【ae】文字3D:动画3D:3D摄像机
  6. 如何Renew你的Office 365开发者订阅
  7. PCI网卡上扩展ROM编程 8.附件
  8. sleep php函数毫秒,sleep()函数介绍
  9. 倍思机械眼六合一智能HUB扩展坞 拓展全功能办公更方便
  10. Java实现记事本(含源码)