小学四则运算

1.PSP表格

计划 计划完成需要的时间 实际完成需要的时间
估计这个任务需要多少时间,并规划大致工作步骤 15  10
需求分析 (包括学习新技术) 150 120
生成设计文档 30 20
设计复审 10 8
代码规范 (为目前的开发制定合适的规范) 10 10
具体设计 30 20
具体编码 20 15
代码复审 20 10
测试(自我测试,修改代码,提交修改) 30 30
测试报告 20 15
计算工作量 20 10
事后总结 ,并提出过程改进计划 10 20
总计 365 288

2.生成四则运算算式和答案

3.代码

package szyx;

import java.util.Scanner;

public class main {

    public static void main(String[] args){

        System.out.println("请选择功能:");
        System.out.println("    1. 四则运算生成器");
        System.out.println("    2. 答案对比");
        System.out.print("请输入你的选择[1/2]:");
        int choose = new Scanner(System.in).nextInt();

        switch (choose){
            case 1:
                ProducerController producerController = new ProducerController();
                producerController.ConstructProblem();;break;
            case 2:
                JudgeAnswerController judgeAnswerController = new JudgeAnswerController();
                judgeAnswerController.start();;break;
            default:
                System.out.println("输入不正确,请输入1或2");main(args);break;
        }
    }
}
package szyx;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.InputMismatchException;
import java.util.Random;
import java.util.Scanner;

public class ProducerController{

    public void ConstructProblem(){
        System.out.println("----------欢迎来到四则运算生成器----------\n");
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入生成题目个数:");
            int num = scanner.nextInt();
            System.out.print("请输入最大自然数:");
            int range = scanner.nextInt();

            generateProblem(num, range);
        }catch (InputMismatchException e){
            System.out.println("请输入数字。\n\n\n");
            ConstructProblem();
        } catch (IOException e) {
            System.out.println("文件创建失败");
        }
    }

    /**
     * 输出到文件
     * @param num
     * @param range
     * @throws IOException
     */
    public void generateProblem(int num, int range) throws IOException {
        //项目根目录生成
        File exercises = new File("Exercises.txt");
        File answers = new File("Answers.txt");

        if (exercises.exists() || answers.exists()){
            exercises.delete();
            answers.delete();
        }

        if (exercises.createNewFile() && answers.createNewFile()){
            FileOutputStream exercisesOutput = new FileOutputStream(exercises);
            PrintStream exercisesPrintStream = new PrintStream(exercisesOutput);

            FileOutputStream answersOutput = new FileOutputStream(answers);
            PrintStream answersPrintStream = new PrintStream(answersOutput);
            Random random = new Random();

            CreateFraction createFraction = new CreateFraction();
            CreateInteger createInteger = new CreateInteger();

            String[] problem = new String[2];
            for(int i = 1; i <= num; i++){
                int choose = random.nextInt(2);
                if (choose == 0){
                    problem = createFraction.createProblem(range);
                }else {
                    problem = createInteger.createProblem(range);
                }
                outputFile(i, problem, exercisesPrintStream, answersPrintStream);
            }

            exercisesOutput.close();
            answersOutput.close();
            exercisesPrintStream.close();
            answersPrintStream.close();

            System.out.println("文件创建成功 ");
        }
    }

    public void outputFile(int i, String problem[], PrintStream... var){
        try {
            var[0].println(i + ". " + problem[0]);
            var[1].println(i + ". " + problem[1]);
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("程序内部出错了");
        }
    }
}
package szyx;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class JudgeAnswerController {

    public void start(){
        System.out.print("请输入待验证答案路径:");
        Scanner scanner = new Scanner(System.in);
        String exerciseFilePath = scanner.next();
        System.out.print("请输入程序生成答案文件路径:");
        String answerFilePath = scanner.next();

        try {
            List<String> exerciseAnswers = exerciseFileReader(exerciseFilePath);
            List<String> answers = answerReader(answerFilePath);

            List<String> correct = new ArrayList<>();
            List<String> wrong = new ArrayList<>();

            int min = Math.min(exerciseAnswers.size(), answers.size());
            int num = 1;
            for (int i = 0; i < min; i++){
                if (exerciseAnswers.get(i).equals(answers.get(i))){
                    correct.add(String.valueOf(num++));
                }else {
                    wrong.add(String.valueOf(num++));
                }
            }

            File grade = new File("Grade.txt");
            if (grade.exists()){
                grade.delete();
            }
            if (grade.createNewFile()){
                FileOutputStream gradeOutput = new FileOutputStream(grade);
                PrintStream gradePrintStream = new PrintStream(gradeOutput);
                String corrects = String.join(",", correct);
                gradePrintStream.println("Correct:" + correct.size() +
                        " (" + corrects + ")");
                String wrongs = String.join(",", wrong);
                gradePrintStream.println("Wrong:" + wrong.size() +
                        " (" + wrongs + ")");
            }

            System.out.println("判定完成");

        } catch (FileNotFoundException e) {
            System.out.println("文件不存在");
        } catch (IOException e) {
            System.out.println("文件读入异常");
        }
    }

    public List<String> exerciseFileReader(String path) throws IOException {
        BufferedReader exerciseReader = new BufferedReader(new FileReader(path));
        String exerciseAnswer = "";
        List<String> exerciseAnswers = new ArrayList<>();
        while ((exerciseAnswer = exerciseReader.readLine()) != null){
            String[] split = exerciseAnswer.split("=");
            if (split.length >= 2){
                exerciseAnswers.add(split[1]);
            }else {
                exerciseAnswers.add(" ");
            }
        }
        return exerciseAnswers;
    }

    public List<String> answerReader(String path) throws IOException {
        BufferedReader answerReader = new BufferedReader(new FileReader(path));
        String answer = "";
        List<String> answers = new ArrayList<>();
        while ((answer = answerReader.readLine()) != null){
            String[] split = answer.split(" ");
            answers.add(split[1]);
        }
        return answers;
    }
}
package szyx;
import java.util.Random;

public class CreateInteger {

    private static final String[]  OPERATOR = {"+", "-", "*", "÷"};

    /**
     * 整数生成器
     * @param range
     */
    public String[] createProblem(int range){
        Random random = new Random();
        int operatorCount = 1 + random.nextInt(3); //随机操作符的个数(1-3个)
        int operand[] = new int[operatorCount + 1]; //操作数个数
        int[] operatorIndex = index(operatorCount, 4, random);

        for(int i = 0; i < operatorCount + 1; i++){
            operand[i] = random.nextInt(range);
        }

        String formula = stitchingFormula(operatorCount, operand, operatorIndex);

        //计算结果
        Calculator calculator = new Calculator();
        int res = calculator.algorithm(formula);
        String formulaRes[] = new String[2];

        if (res > 0){
            formulaRes[0] = formula;
            formulaRes[1] = String.valueOf(res);
        }else {
            return createProblem(range);
        }
        return formulaRes;
    }



    /**
     * 随机产生操作符的下标数组
     * @param operatorCount
     * @param operatorTotal
     * @param random
     * @return
     */
    public int[] index(int operatorCount,int operatorTotal, Random random){
        int similar = 0;
        int[] operatorIndex = new int[operatorCount];
        for(int i = 0; i < operatorCount; i++){
            operatorIndex[i] = random.nextInt(operatorTotal);
        }

        for (int i : operatorIndex) {
            if(operatorIndex[0] == i) {
                similar++;
            }
        }
        if(similar == operatorCount && operatorCount != 1){
            return index(operatorCount, operatorTotal, random); //保证一个式子里至少有2个不同的操作符,若所有操作符下标都一样,则重新产生操作符下标
        } else {
            return operatorIndex;
        }
    }

    /**
     * 拼接式子
     * @param operatorCount
     * @param operand
     * @param operatorIndex
     * @return
     */
    public String stitchingFormula(int operatorCount, int operand[], int[] operatorIndex){
        int bracketForm = new Random().nextInt(2);//式子形态
        StringBuilder formula = new StringBuilder();
        switch (operatorCount){
            case 1:
                // 1+2型
                formula.append(operand[0])
                        .append(" ")
                        .append(OPERATOR[operatorIndex[0]])
                        .append(" ")
                        .append(operand[1])
                        .append(" ")
                        .append("=");
                break;
            case 2:{
                // 1+2+3 型
                if (bracketForm == 0){
                    formula.append(operand[0])
                            .append(" ")
                            .append(OPERATOR[operatorIndex[0]])
                            .append(" ")
                            .append(operand[1])
                            .append(" ")
                            .append(OPERATOR[operatorIndex[1]])
                            .append(" ")
                            .append(operand[2])
                            .append(" ")
                            .append("=");

                }else {
                    //1+(2+3)型
                    formula.append(operand[0])
                            .append(" ")
                            .append(OPERATOR[operatorIndex[0]])
                            .append(" ")
                            .append("(")
                            .append(" ")
                            .append(operand[1])
                            .append(" ")
                            .append(OPERATOR[operatorIndex[1]])
                            .append(" ")
                            .append(operand[2])
                            .append(" ")
                            .append(")")
                            .append(" ")
                            .append("=");
                }break;
            }
            case 3:{
                if (bracketForm == 0){
                    //1+((2+3)-4)型
                    formula.append(operand[0])
                            .append(" ")
                            .append(OPERATOR[operatorIndex[0]])
                            .append(" ")
                            .append("((")
                            .append(" ")
                            .append(operand[1])
                            .append(" ")
                            .append(OPERATOR[operatorIndex[1]])
                            .append(" ")
                            .append(operand[2])
                            .append(" ")
                            .append(")")
                            .append(" ")
                            .append(OPERATOR[operatorIndex[2]])
                            .append(" ")
                            .append(operand[3])
                            .append(" ")
                            .append(")")
                            .append(" ")
                            .append("=");
                }else {
                    //(1+2)+(3+4)型
                    formula.append("(")
                            .append(" ")
                            .append(operand[0])
                            .append(" ")
                            .append(OPERATOR[operatorIndex[0]])
                            .append(" ")
                            .append(operand[1])
                            .append(" ")
                            .append(")")
                            .append(" ")
                            .append(OPERATOR[operatorIndex[1]])
                            .append(" ")
                            .append("(")
                            .append(" ")
                            .append(operand[2])
                            .append(" ")
                            .append(OPERATOR[operatorIndex[2]])
                            .append(" ")
                            .append(operand[3])
                            .append(" ")
                            .append(")")
                            .append(" ")
                            .append("=");
                }break;
            }
        }
        return formula.toString();
    }
}
package szyx;
import java.util.Random;

public class CreateFraction {

    private static final String OPERATOR[] = {"+", "-"};

    /**
     * 真分数生成器
     * @param range
     */
    public String[] createProblem(int range){
        Random random = new Random();
        int operatorCount = 1 + random.nextInt(3); //操作符的个数1-3

        CreateInteger create = new CreateInteger();
        int[] operatorIndex = create.index(operatorCount,2, random); //操作符的下标

        //生成第一个操作数
        int[] coprimeNumber1 = createCoprimeNumbers(range, random);
        int x = coprimeNumber1[0];
        int y = coprimeNumber1[1];

        String s = shamToProperFraction(x, y);

        for(int i=0; i < operatorCount; i++){
            //生成剩下的操作数
            int[] coprimeNumber = createCoprimeNumbers(range, random);
            int numx = coprimeNumber[0];
            int numy = coprimeNumber[1];

            String currentOpreator = OPERATOR[operatorIndex[i]];

            if(currentOpreator.equals("+")){  //加法
                x = x * numy + y * numx;
                y = y * numy;
            }else {   //减法
                int count = 0;
                while(x * numy - y * numx < 0){ //差为负数
                    coprimeNumber = createCoprimeNumbers(range, random);
                    numx = coprimeNumber[0];
                    numy = coprimeNumber[1];
                    count++;
                    if (count >= 5){
                        numx = x - 1;
                        numy = y;
                    }
                }
                x = x * numy - y * numx;
                y = y * numy;
            }

            String num = shamToProperFraction(numx, numy);
            s += currentOpreator + num;
        }

        int greatFactor = greatFactor(x,y);
        x /= greatFactor; //最终结果化简
        y /= greatFactor;

        String res = shamToProperFraction(x, y);
        s += "=";

        String formulaRes[] = {s, res};
        return formulaRes;
    }

    /**
     * 求最大公因数
     * @param x
     * @param y
     * @return
     */
    public int greatFactor(int x,int y) {
        while(true){
            if(x % y == 0){
                return y;
            }
            int temp = y;
            y = x % y;
            x = temp;
        }
    }

    /**
     * 生成一对互质数
     * @param range
     * @param random
     * @return
     */
    public int[] createCoprimeNumbers(int range, Random random){
        int x = 1 + random.nextInt(range);
        int y = 1 + random.nextInt(range);
        int greatFactor = greatFactor(x, y);
        x /= greatFactor;
        y /= greatFactor;
        int numbers[] = {x, y};
        return numbers;
    }

    /**
     * 假分数转化为真分数
     * @param x 分子
     * @param y 分母
     * @return
     */
    public String shamToProperFraction(int x, int y){
        if (x > y){
            int n = x / y;
            x = (x - n * y);
            if (x == 0){
                return String.valueOf(n);
            }
            return n + "'" + x + "/" + y;
        }else if (x == y){
            return "1";
        }else if (y == 1){
            return String.valueOf(x);
        }else if (x == 0){
            return "0";
        }
        return x + "/" + y;
    }
}
package szyx;
import java.util.HashMap;
import java.util.Stack;
public class Calculator {

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

        String formula = s.replaceAll(" ", "");

        for (int i = 0; i < formula.length();) {
            StringBuilder digit = new StringBuilder();  //StringBuilder类中的方法主要偏重于对于字符串的变化,例如追加、插入和删除等,这个也是StringBuffer和String类的主要区别。
            char c = formula.charAt(i); //将式子字符串切割为c字符
            while (Character.isDigit(c)) { //判断字符是否为10进制数字,将一个数加入digit
                digit.append(c);
                i++;
                if (i < formula.length()){
                    c = formula.charAt(i);
                }else {
                    break;
                }
            }
            if (digit.length() == 0){ //当前digit里面已经无数字,即当前处理符号
                switch (c) {
                    case '(': {
                        operatorStack.push(String.valueOf(c));//如果是(   转化为字符串压入字符栈
                        break;
                    }
                    case ')': { //遇到右括号了计算,因为(的优先级最高
                        String stmp = operatorStack.pop(); //如果是),将符号栈栈顶元素取到
                        while (!operatorStack.isEmpty() && !stmp.equals("(")) { //当前符号栈里面还有+ - * /
                            int a = numStack.pop();  //取操作数a,b
                            int b = numStack.pop();
                            int result = calculate(b, a, stmp); //计算
                            if(result < 0)
                                return  -1;
                            numStack.push(result); //将结果压入栈
                            stmp = operatorStack.pop(); //符号指向下一个计算符号
                        }
                        break;
                    }
                    case '=': { //遇到等号了计算
                        String stmp;
                        while (!operatorStack.isEmpty()) { //当前符号栈里面还有+ - * /,即还没有算完
                            stmp = operatorStack.pop();
                            int a = numStack.pop();
                            int b = numStack.pop();
                            int result = calculate(b, a, stmp);
                            if(result < 0)
                                return  -1;
                            numStack.push(result);
                        }
                        break;
                    }
                    default: {  //不满足之前的任何情况
                        String stmp;
                        while (!operatorStack.isEmpty()) { //如果符号栈有符号
                            stmp = operatorStack.pop(); //当前符号栈,栈顶元素
                            if (hashMap.get(stmp) >= hashMap.get(String.valueOf(c))) { //比较优先级
                                int a = numStack.pop();
                                int b = numStack.pop();
                                int result =calculate (b, a, stmp);
                                if(result < 0)
                                    return  -1;
                                numStack.push(result);
                            }
                            else {
                                operatorStack.push(stmp);
                                break;
                            }

                        }
                        operatorStack.push(String.valueOf(c));  //将符号压入符号栈
                        break;
                    }
                }
            }
            else { //处理数字,直接压栈
                numStack.push(Integer.valueOf(digit.toString()));  //Integer.valueof()返回的是Integer对象,而Integer.parseInt()返回的是int型
                continue; //结束本次循环,回到for语句进行下一次循环,即不执行i++(因为此时i已经指向符号了)
            }
            i++;
        }
        return numStack.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;
    }
}

4.结果

 

 

 

 

 

 

 

 

 

posted @ 2021-09-27 22:07  yyyy1998  阅读(53)  评论(0)    收藏  举报