个人项目实战——用Java实现四则运算功能

我们老师最近布置了一项作业,让每个人用Java语言实现整数或是分数的四则运算功能。

具体需求如下:

1、程序可接收一个输入参数n,然后随机产生n道加减乘除(分别使用符号+-*÷来表示)练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间。

2、每个练习题至少要包含2种运算符。同时,由于小学生没有分数与负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3÷5+2=2.6,2-5+10=7等算式。

3、练习题生成好后,将你的学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中,不要输出额外信息,文件目录与程序目录一致。

4、支持有括号的运算式,包括出题与求解正确答案。注意,算式中存在的括号数必须大于2对,且不得超过运算符的个数。

5、支持真分数的出题与运算(只需要涵盖加减法即可),例如:1/6 + 1/8 + 2/3= 23/24。注意在实现本功能时,需支持运算时分数的自动化简,比如 1/2+1/6=2/3,而非4/6,且计算过程中与结果都须为真分数

我认为,整个项目的难点就在于将中缀表达式转化为后缀表达式,并将其计算出来。在这里我运用了逆波兰表达式和调度场算法。

下面是我的部分代码

public int algorithm(String s) {
        //放数字
        Stack stack1 = new Stack<>();
        //放操作符
        Stack stack2 = new Stack<>();
        //存放运算符优先级
        HashMap hashmap = new HashMap<>();
        hashmap.put("(", 0);
        hashmap.put("+", 1);
        hashmap.put("-", 1);
        hashmap.put("*", 2);
        hashmap.put("÷", 2);

        for (int i = 0; i < s.length();) {
            //设置可变长的字符串
            StringBuffer digit = new StringBuffer();
            //将式子字符串切割为c字符
            char c = s.charAt(i);
            //判断字符是否为10进制数字,将一个数加入digit
            while (Character.isDigit(c)) {
                digit.append(c);
                i++;
                c = s.charAt(i);
            }
            //当前digit里面已经无数字,即当前处理符号
            if (digit.length() == 0){
                switch (c) {
                    case '(': {
                        stack2.push(String.valueOf(c));
                        break;
                    }
                    //遇到右括号了计算,因为(的优先级最高
                    case ')': {
                        String stmp = stack2.pop();
                        while (!stack2.isEmpty() && !stmp.equals("(")) {
                            int a = stack1.pop();
                            int b = stack1.pop();
                            int sresulat = calculate(b, a, stmp);
                            if(sresulat<0)
                                return  -1;
                            stack1.push(sresulat);
                            //符号指向下一个计算符号
                            stmp = stack2.pop();
                        }
                        break;
                    }
                    case '=': {
                        String stmp;
                        while (!stack2.isEmpty()) {
                            stmp = stack2.pop();
                            int a = stack1.pop();
                            int b = stack1.pop();
                            int sresulat = calculate(b, a, stmp);
                            if(sresulat<0)
                                return  -1;
                            stack1.push(sresulat);
                        }
                        break;
                    }

                    default: {
                        String stmp;
                        while (!stack2.isEmpty()) {
                            stmp = stack2.pop();
                            //比较优先级
                            if (hashmap.get(stmp) >= hashmap.get(String.valueOf(c))) {
                                int a = stack1.pop();
                                int b = stack1.pop();
                                int sresulat =calculate (b, a, stmp);
                                if(sresulat<0)
                                    return  -1;
                                stack1.push(sresulat);
                            }
                            else {
                                stack2.push(stmp);
                                break;
                            }

                        }
                        //将符号压入符号栈
                        stack2.push(String.valueOf(c));
                        break;
                    }
                }
            }
            else {
                //处理数字
                stack1.push(Integer.valueOf(digit.toString()));
                continue;
            }
            i++;
        }
        //返回栈底得到答案
        return stack1.peek();
    }
private int calculate(int a, int b, String stmp) { //计算a stmp b的值
        int res = 0;
        char s = stmp.charAt(0);
        switch (s) {
            case '+': {
                res = a + b;
                break;
            }
            case '-': {
                //判断是否产生负数
                res = a - b;
                break;
            }
            case '*': {
                res = a * b;
                break;
            }
            case '÷': {
                if(b==0)
                    return -1;
                //判断是否产生小数
                else if(a%b!=0)
                    return -2;
                else
                    res = a / b;
                break;
            }
        }
        return res;
    }

这是算法部分

public class Create {
    public String createProblem(){  //产生整数式子
        Random r = new Random();
        String[] opertor = {"+","-","*","÷"};
        //操作符的个数
        int operatorNum = 3+r.nextInt(3);
        //新建数组来保存操作数
        int[] number = new int[operatorNum+1];
        //操作符的下标
        int[] arr = index(operatorNum);
        String s = new String();

        for(int j=0;j=0){
            s+=answer;
        }else {
            //递归
            return createProblem();
        }

        return s;

    }


    public int[] index(int n){ //产生操作符的下标数组
        Random random = new Random();
        int similar=0;
        int[] a = new int[n];
        for(int j=0;j

产生整数式子

public class ProperFraction { 
    public String createProblem(){
        Random r = new Random();
        String[] operator = {"+","-"};
        int operatorCount = 3+r.nextInt(3); 


        int[] index = index2(operatorCount); 

        int sumx = 1+r.nextInt(10); 
        int sumy = 1+r.nextInt(20);
        int g = maxG(sumx,sumy);
        sumx/=g;
        sumy/=g;

        int[] fenshu = huajian(sumx, sumy);
        sumx = fenshu[0];
        sumy = fenshu[1];
        //第一个数
        String s=sumx+"/"+sumy; 

        for(int i=0;i= fenmu) {
            fenzi = 1 + r.nextInt(10);
            fenmu = 1 + r.nextInt(20);
            int g = maxG(fenzi, fenmu);
            fenzi = fenzi / g;
            fenmu = fenmu / g;
        }
        int[] fenshu = new int[2];
        fenshu[0] = fenzi;
        fenshu[1] = fenmu;
        return fenshu;
    }
}

产生分数式子

这三块便是整个项目最核心的部分便是这三个部分。

接下来就是项目功能的展示

在命令行进行测试

个人项目实战——用Java实现四则运算功能_第1张图片

个人项目实战——用Java实现四则运算功能_第2张图片

得到result.txt文件

下面是我的PSP

PSP2.1

任务内容

计划共完成需要的时间(h)

实际完成需要的时间(h)

Planning

计划

2

3

·        Estimate

·   估计这个任务需要多少时间,并规划大致工作步骤

2

3

Development

开发

46.5

69.5

·        Analysis

·         需求分析 (包括学习新技术)

2

4

·        Design

·         具体设计

1

1

·        Coding

·         具体编码

38

46

·        Code Review

·         代码复审

0.5

0.5

·        Test

·         测试(自我测试,修改代码,提交修改)

5

18

Reporting

报告

0.8

1

·         Size Measurement

·         计算工作量

0.3

0.5

·         Postmortem & Process Improvement Plan

·         事后总结, 并提出过程改进计划

0.5

0.5

 

改进

       我在生成括号的地方偷了个小懒,没有用生成随机数的方式来让式子随机生成括号的位置,我想,在以后,这是可以再进行改进的地方

个人感悟:

       这次的项目让我感触颇多,同时也让我收获了许多。

       由于很久没有写过Java程序了,以至于我都忘记了idea里的环境怎么配,只得一点一点从头再来。在开始写这个作业的时候,我有点无从下手,于是就一个一个地把需求在纸上罗列了出来,就是这样

个人项目实战——用Java实现四则运算功能_第3张图片

这才使我的思路逐渐清晰。在代码基本完成,开始测试的时候又出了很多的问题,有时我在命令行测试的时候会出现一些莫名其妙的错误,比如找不到主类,数组下标越界,甚至直接告诉我我的内存不够了,在解决这些问题的时候真的是心力交瘁,有的时候甚至想,算了算了,直接随便找一份交上去算了,但是后来还是休息之后,继续和这些bug作斗争!

虽说这次作业耗费了很多的精力,但是在这次的项目中,我收获了宝贵的经验以及技术的大幅进步,哈哈哈哈哈,程序员不就是这样嘛,在一次又一次的实战中不断进步,不断成长!
 

 

你可能感兴趣的:(个人项目实战——用Java实现四则运算功能)