对于四则运算,大家都很熟悉,如果为问你1+1=?你可能立即会觉得自己遭受到了莫大的侮辱。并且大声质问我:你觉得我智商有问题吗? !
息怒。
换一个问法:
你能否把自己计算四则运算的方法,描述成严格的规则,让程序替我们进行计算哪?
ennnnnn~~~
对于这个问题,可能有人会说:这不是很简单吗?的确,这不是一个很难的问题,但对于一个编程能力薄弱的我来说就不是很简单了。
我们把这个问题具体化,要求如下:
- 为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符。同时,由于小学生没有分数与负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3/5+2=2.6,2-5+10=7等算式。
- 练习题生成好后,将你的学号
- 当程序接收的参数为4时,以下为输出文件示例。
下面我们具体分析一下,对于这个问题我们需要怎么去考虑:
1、需求分析
1.根据题目要求,要生成3,4和5个数字的运算表达式,每个数字在0到100之间;
2.表达式中包含包含3,4,和5个运算符;
3.表达式计算结果不能是负数;
4.每次运算都是整数,计算结果为整数;
5.结果输出到特定文件;
2、设计功能
输入整数N,在命令窗口随机产生N道四则运算表达式,表达式满足上面要求,将表达式和结果保存到text文件中。
3、设计实现
程序类图:
main--------------------------------主函数
INT ---------------------------------判断结果是否为整数
arithemtic--------------------------表达式接收函数
parseExp---------------------------对输入的表达式进行解析
calulate-----------------------------结果计算函数
4、测试运行
Eclipse窗口测试结果:
Cmd窗口测试结果:
5、核心代码
对合法表达式进行解析
public static String parseExp(String expression) { expression=expression.replaceAll("\s+", "").replaceAll("^\((.+)\)$", "$1"); String checkExp="\d"; String minExp="^((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))[\+\-\*\/]((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))$"; //最小表达式计算 if(expression.matches(minExp)) { String result=calculate(expression); return Double.parseDouble(result)>=0?result:"["+result+"]"; } //计算不带括号的四则运算 String noParentheses="^[^\(\)]+$"; String priorOperatorExp="(((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))[\*\/]((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\])))"; String operatorExp="(((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))[\+\-]((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\])))"; if(expression.matches(noParentheses)){ Pattern patt=Pattern.compile(priorOperatorExp); Matcher mat=patt.matcher(expression); if(mat.find()){ String tempMinExp=mat.group(); expression=expression.replaceFirst(priorOperatorExp, parseExp(tempMinExp)); }else{ patt=Pattern.compile(operatorExp); mat=patt.matcher(expression); if(mat.find()){ String tempMinExp=mat.group(); expression=expression.replaceFirst(operatorExp, parseExp(tempMinExp)); } } return parseExp(expression); } return parseExp(expression); }
结果计算函数:
public static String calculate(String exp){ exp=exp.replaceAll("[\[\]]", ""); String number[]=exp.replaceFirst("(\d)[\+\-\*\/]", "$1,").split(","); BigDecimal number1=new BigDecimal(number[0]); BigDecimal number2=new BigDecimal(number[1]); BigDecimal result=null; String operator=exp.replaceFirst("^.*\d([\+\-\*\/]).+$", "$1"); if("+".equals(operator)){ result=number1.add(number2); }else if("-".equals(operator)){ result=number1.subtract(number2); }else if("*".equals(operator)){ result=number1.multiply(number2); }else if("/".equals(operator)){ result=number1.divide(number2,2, BigDecimal.ROUND_HALF_EVEN); } return result!=null?result.toString():null; }
6、PSP展示
PSP2.1 | 任务内容 | 计划完成的时间(h) | 实际完成需要的时间(h) |
---|---|---|---|
PLanning | 计划 | 0.5 | 1 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 0.5 | 1 |
Developmet | 开发 | 5 | 7 |
Analysis | 需求分析(包括学习新技术) | 0.3 | 0.5 |
Design Spec | 生成设计文档 | 0.5 | 0.5 |
Design Revie | 设计复审(和同事审核设计文档) | 0.3 | 0.5 |
Coding Standard | 代码规范 | 0.2 | 0.3 |
Design | 具体设计 | 0.4 | 0.6 |
Coding | 具体编码 | 2.3 | 3.6 |
Code Review | 代码复审 | 0.5 | 0.5 |
Test | 测试(自我测试,修改代码,提交修改) | 0.5 | 0.5 |
Reporting | 报告 | 0.3 | 0.5 |
Test Report | 测试报告 | 0.1 | 0.2 |
Size Measurement | 计算工作量 | 0.1 | 0.1 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改机计划 | 0.1 | 0.5 |
项目总结:
在开始的时候,由于没有考虑好除法运算的要求,导致在后面出现不能正除,出现小数的情况,花费了较多时间进行改正,对于表达式的的解析我采用的是正则表达式的方法,由于之前接触过正则表达式,没想到这次用到了,下面是我整理的关于正则表达式的一些基本的语法含义。
^ 表示以什么开始如:^b表示以b字母开头
. 表示任意字符
* 表示前面的字符可以出现任意多次
$ 表示以什么结束如:3$表示以3结尾
? 表示非贪婪模式,正则表达式默认的是贪婪模式,贪婪模式是从后往前匹配
+ 表示前面的字符至少出现一次
{3}出现的次数 {3,}至少出现3次{3,5}至少出现3次最多5次
|表示或关系
s 表示空格S不为空格可以
w表示[A-Za-z0-9]W表示不为w可以
[u4E00-u9FA5]表示汉字如line="study in 南京大学"reg=".*?([u4E00-u9FA5]+大学)"
d表示数字
Github地址:四则运算