java编写一个计算器
来源:互联网 发布:网站如何优化排名 编辑:程序博客网 时间:2024/06/05 06:36
本篇博客来用java编写一个计算器,来计算一个算数表达式,这个表达式支持加减乘除和任意层次的括号嵌套(仅支持圆括号)。
思路设计
首先讨论一下思路。假设有一个算数表达式为(2 + 1) + 200 * 3.2 / (5 * (2 + 6 ))
,我们首先需要按照优先级先计算最内层括号内的表达式,然后再计算外层括号的,直到演化为一个不含括号的普通加减乘除表达式,最终得出一个结果。
代码设计:
子过程:computeFlatExp(String flatExp)
函数用来计算一个不含括号的加减乘除表达式,它先轮训计算乘和除,再轮训计算加和减,直到得出最终结果。
主流程:,不断地发现闭合的括号,然后调用computeFlatExp()
函数计算字表达式的结果,从而简化算数表达式,直到简化为算数表达式不包含括号位置,最后在调用一次computeFlatExp()
函数得出最终结果
代码及分析
下面来看下具体代码的实现。先来看下computeFlatExp()
。
computeFlatExp()子过程
private double computeFlatExp(String flatExp) { // 先递归计算所有乘法和除法 Pattern pattern = Pattern.compile("(?<num1>[\\d\\.]+)\\s*(?<operator>[\\*/])\\s*?(?<num2>[\\d\\.]+)"); Matcher matcher = pattern.matcher(flatExp); while (matcher.find()) { double num1 = Double.parseDouble(matcher.group("num1")); double num2 = Double.parseDouble(matcher.group("num2")); String operator = matcher.group("operator"); double result = operator.contains("*") ? num1 * num2 : num1 / num2; flatExp = flatExp.replace(matcher.group(0), String.valueOf(result)); matcher = pattern.matcher(flatExp); } // 再递归计算所有加法和减法 pattern = Pattern.compile("(?<num1>[\\d\\.]+)\\s*(?<operator>[\\+\\-])\\s*?(?<num2>[\\d\\.]+)"); matcher = pattern.matcher(flatExp); while (matcher.find()) { Double num1 = Double.parseDouble(matcher.group("num1")); Double num2 = Double.parseDouble(matcher.group("num2")); String operator = matcher.group("operator"); double result = operator.contains("+") ? num1 + num2 : num1 - num2; flatExp = flatExp.replace(matcher.group(0), String.valueOf(result)); matcher = pattern.matcher(flatExp); } return Double.parseDouble(flatExp.trim());}
上面的代码思路比较简单,主要的手段就是依赖正则表达式,我在上一篇博客中讨论了java中使用正则表达式的方式,这次要好好用一下了。它从左至右依次抓取并计算所有的例如1.2 * 3.4
或者5.6 / 7.8
之类的乘法和除法的二元表达式,然后再从左至右抓取并计算所有的加法表达式或减法二元表达式,直至剩下最后一个数字为止,最后将这一个表达式变化为数字,并将它转换为Double的对象返回。
主流程
再来看一下主流程的代码
public double compute(String expression) { int start = -1; for (int i = 0; i < expression.length(); i++) { if (expression.charAt(i) == '(') { start = i; } if (expression.charAt(i) == ')') { // 递归来简化问题 String flatExp = expression.substring(start + 1, i); double result = computeFlatExp(flatExp); StringBuilder sb = new StringBuilder(); if (start > 0) { sb.append(expression.substring(0, start - 1)); } sb.append(String.valueOf(result)); if (i < expression.length() - 1) { sb.append(expression.substring(i + 1)); } return compute(sb.toString()); } } // 计算加减乘除 return computeFlatExp(expression);}
上面的代码先记录下来最右侧的左括号,一旦遇到右括号,则意味着找到了一组匹配的括号了,用这种方式来处理括号的嵌套比较有用。找到一组匹配的括号后,就调用computeFlatExp()
子过程来计算匹配到的字表达式,并将计算结果替换到源表达式中,从而简化了整个源表达式。不断重复这个过程,最终将所有括号中的子表达式全部算出来,从而消除了所有的括号。最后再调用一次computeFlatExp()
子过程,从而得出最终结果。
调用方式
再来看一下这个计算器的外部调用方式
public static void main(String[] args) { MyCalculator cal = new MyCalculator(); double result = cal.compute("(2 + 1) + 200 * 3.2 / (5 * (2 + 6 ))");}
上面表达式的计算结果是19.0。
完整的代码
下面是完整的代码
import java.util.regex.Matcher;import java.util.regex.Pattern;public class MyCalculator { public double compute(String expression) { int start = -1; for (int i = 0; i < expression.length(); i++) { if (expression.charAt(i) == '(') { start = i; } if (expression.charAt(i) == ')') { // 递归来简化问题 String flatExp = expression.substring(start + 1, i); double result = computeFlatExp(flatExp); StringBuilder sb = new StringBuilder(); if (start > 0) { sb.append(expression.substring(0, start - 1)); } sb.append(String.valueOf(result)); if (i < expression.length() - 1) { sb.append(expression.substring(i + 1)); } return compute(sb.toString()); } } // 计算加减乘除 return computeFlatExp(expression); } /** * 计算加减乘除,不含括号 * * @param flatExp * @return */ private double computeFlatExp(String flatExp) { // 先递归计算所有乘法和除法 Pattern pattern = Pattern.compile("(?<num1>[\\d\\.]+)\\s*(?<operator>[\\*/])\\s*?(?<num2>[\\d\\.]+)"); Matcher matcher = pattern.matcher(flatExp); while (matcher.find()) { double num1 = Double.parseDouble(matcher.group("num1")); double num2 = Double.parseDouble(matcher.group("num2")); String operator = matcher.group("operator"); double result = operator.contains("*") ? num1 * num2 : num1 / num2; flatExp = flatExp.replace(matcher.group(0), String.valueOf(result)); matcher = pattern.matcher(flatExp); } // 再递归计算所有加法和减法 pattern = Pattern.compile("(?<num1>[\\d\\.]+)\\s*(?<operator>[\\+\\-])\\s*?(?<num2>[\\d\\.]+)"); matcher = pattern.matcher(flatExp); while (matcher.find()) { Double num1 = Double.parseDouble(matcher.group("num1")); Double num2 = Double.parseDouble(matcher.group("num2")); String operator = matcher.group("operator"); double result = operator.contains("+") ? num1 + num2 : num1 - num2; flatExp = flatExp.replace(matcher.group(0), String.valueOf(result)); matcher = pattern.matcher(flatExp); } return Double.parseDouble(flatExp.trim()); } public static void main(String[] args) { MyCalculator cal = new MyCalculator(); double result = cal.compute("(2 + 1) + 200 * 3.2 / (5 * (2 + 6 ))"); }}
如果你有疑问,或者有更好的方案,欢迎在评论区和我讨论。
- java编写一个计算器
- 用java编写一个计算器
- 用java编写一个简单的计算器
- Java编写一个计算器程序过程介绍
- 用Java编写的一个小计算器
- 用java编写一个简单计算器
- 怎样用Java编写一个简单的计算器
- 用java编写一个简单计算器
- JavaBean编写一个计算器
- 使用Java AWT编写一个简单的计算器
- java编写的计算器
- java编写的计算器
- Java+JSP编写计算器
- JAVA编写简易计算器
- java编写的计算器
- java编写计算器
- Java编写计算器
- java代码编写计算器
- 网络编程
- objective-c 编程基础(3.7 Foundation框架之字典)
- MVC框架
- Android判断是否为Wifi
- 文本框输入总是从中间输入,并且只能输入一行
- java编写一个计算器
- 第五届“图灵杯”NEUQ-ACM程序设计大赛 F题 字符串处理哈夫曼树
- 基于窗口与基于速率的拥塞控制
- 树莓派(RPi) CentOS7安装配置PHP7
- Rest模式get,put,post,delete含义与区别(转)
- 一种报表输出的设计方法
- IDEA常用快捷键
- Python的运算符
- 1078. 字符串压缩与解压(未拿满分)