首页 > 编程语言 >Java实现四则运算生成器

Java实现四则运算生成器

时间:2023-09-27 16:25:23浏览次数:50  
标签:return List 四则运算 生成器 Fraction new action Java public

这个作业属于哪个课程 计科二班
这个作业要求在哪里 结对项目
这个作业的目标 熟悉结对编程

项目成员

龙新超 3121004921 github链接:龙新超github
艾孜海尔江 3121004900 github链接:海尔江github

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 15 15
· Estimate · 估计这个任务需要多少时间 15 15
Development 开发 715 695
· Analysis · 需求分析 (包括学习新技术) 150 150
· Design Spec · 生成设计文档 15 15
· Design Spec · 设计复审 20 20
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 20 40
· Design · 具体设计 60 40
· Coding · 具体编码 240 250
· Code Review · 代码复审 120 90
· Test · 测试(自我测试,修改代码,提交修改) 90 90
Reporting 报告 60 50
· Test Repor · 测试报告 20 20
· Size Measurement · 计算工作量 20 15
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 20 15
· 合计 790 760

设计实现

项目结构


实体类:分数整数Fraction类,表达式OperationExpression
工具类:DuplicateCheck
服务类:CaculateService,CheckService,getEpression
入口:OperationPro

设计思路

考虑到分数的实现,所以应将整数与分数作为一个对象来处理,即整数就是分母为1的分数。也因此做了实体类Fraction

受到Fraction启发,做了实体类OperationExpression,它的属性包含了表达式及其答案

题目生成设计思路:

于是就可以用一个OperationExpression对象e,运用getExpression的getExp方法生成一个为e的表达式,getExp()方法中调用了CalculateService的calculate()计算方法得到答案。calculate()方法中产生了负数则会返回空值,可根据这个空值判断表达式是否存在负数,若存在则丢弃重新生成。还要进行DuplicateCheck类的查重。通过上述步骤,即可生成一道题目。

关键代码

  1. getExpression
 public class getExpression {
    private static Random r = new Random();
    static List l = new ArrayList();


    //获得字符串集合,并生成表达式
    public List getExp(OperationExpression e,int limit){
        Fraction f1 = new Fraction(r.nextBoolean(),limit);

        List stringList = new ArrayList();
        List l = new ArrayList();

        l.add(f1);
        stringList.add(f1.toString());
        int a = r.nextInt(3); // [0,3),取值为0/1/2,随机生成运算符个数
        do{
            express(e,l,stringList,limit);
            a--;
        }while (a>=0);

        Fraction f =CalculateService.calculate(l);
        if(f==null){
            return null;
        }
        e.setRes(f);
        e.setStringList(stringList);
        return stringList;
    }

    static void express(OperationExpression e,List l,List stringList,int limit){
        Fraction f = new Fraction(r.nextBoolean(),limit);
        //out.println(f.toString()+"f..");

        int a = r.nextInt(4); //取值范围:[0,4)中的0/1/2/3,随机取运算符
        switch (a){         //0:加,1:减,2:乘,3:除
            case 0: l.add("+");l.add(f);
                stringList.add("+");stringList.add(f.toString());
                break;
            case 1:
                //检查是否存在e1-e2<0的情况,存在则应调换位置
//                out.println(l+"测试");
//                out.println(stringList+"测试");
                l.add("-");l.add(f);
                stringList.add("-");stringList.add(f.toString());
                break;
            case 2: l.add("×");l.add(f);
                stringList.add("×");stringList.add(f.toString());
                break;
            case 3: l.add("÷");l.add(f);
                stringList.add("÷");stringList.add(f.toString());
                break;
            default:
                out.println("出错");
        }
        e.setList(l);
    }
}

2.CaculateService

public class CalculateService {
    /**
     * 中序变为后序
     * @param list
     * @return
     */
    public static Stack toPostFix(List list){
        Stack num = new Stack();
        Stack<String> action = new Stack<>();
        int symble = 0;
        for (Object o : list) {
            symble = flag(o, num, action);
            switch (symble) {
                case 1://数字直接入栈
                    num.push(o);
                    break;
                case 2://操作符栈为空直接入栈
                    action.push((String) o);
                    break;
                case 3://当前操作符比栈顶操作符优先级高入栈
                    action.push((String) o);
                    break;
                case 4:
                    //弹出所有比当前操作符优先级高的,直到遇到左括号或者为空
                    while (!action.empty() && action.peek()!="(" && !prior((String)o,action.peek())){
                        num.push(action.pop());//action弹栈并压入number
                    }
                    action.push((String) o);//操作符压栈
                    break;
                case 5://左括号无条件入操作栈
                    action.push((String) o);
                    break;
                case 6:
                    first: while (!action.isEmpty()) {//action弹栈并压入number栈直到遇到左括号
                        String temp = action.pop();
                        if (temp.equals("(")) {
                            break first;
                        } else {
                            num.push(temp);
                        }
                    }
                    break;
                default:
                    break;
            }
        }

        Stack temp = new Stack();
        //将剩下的操作符压入number栈中
        for (String s : action) {
            num.push(s);
        }
        //反序
        for (Object o : num) {
            temp.push(o);
        }
        return temp;
    }
    /**
     * 中序转后序表达式的各种逻辑判断,将判断的结果送入toPostfix()进行各种情况的具体逻辑处理
     *
     * @param o
     * @param number number栈
     * @param action action栈
     * @return 返回各种情况的symbol
     */
    public static int flag(Object o, Stack number, Stack<String> action) {
        if (o instanceof Fraction)
            return 1;// number
        //是操作符
        String s = (String)o;
        if (s.matches("(\\+)|(\\-)|(\\×)|(\\÷)")) {
            if (action.isEmpty()) {
                return 2;// action为空
            } else if (prior(s, action.peek())) {
                return 3;// action不为空,操作符优先级高于栈顶操作符
            } else {
                return 4;// action不为空,操作符优先级不高于栈顶操作符
            }

        }
        if (s.matches("\\("))
            return 5;// 左括号
        if (s.matches("\\)"))
            return 6;// 右括号
        //都不是
        return 0;

    }

    /**
     * 判断操作符和栈顶操作符的优先级
     * @param s1 操作符
     * @param s2 栈顶操作符
     * @return 优先级
     */
    public static Boolean prior(String s1, String s2) {
        if (s2.matches("\\(")) 
            return true;
        if (s1.matches("(\\×)|(\\÷)") && s2.matches("(\\+)|(\\-)"))
            return true;
        return false;
    }
    public static Fraction calculate(List list){

        Stack stack = toPostFix(list);
        Stack<Fraction> newStack = new Stack();
        for (Object o : stack) {
            if(o instanceof Fraction){
                
                newStack.push((Fraction) o);
            }else {
                
                if(newStack.size()<2){
                    
                    break;
                }
                Fraction a = newStack.pop();
                Fraction b = newStack.pop();
                switch ((String) o) {
                    case "+":
                        newStack.push(b.add(a));
                        break;
                    case "-":
                        Fraction fraction = b.sub(a);
               
                        if(fraction.getNominator()<=0||fraction.getDenominator()<=0){
                            return null;
                        }
                        newStack.push(fraction);
                        break;
                    case "×":
                        newStack.push(b.muti(a));
                        break;
                    case "÷":
                        newStack.push(b.div(a));
                        break;
                    default:
                        break;
                }
            }
        }
        return newStack.pop();
    }
}

3.DuplicateService

public class DuplicateCheck {
    //l为判断的表达式集合,allList是已经存在的所有表达式集合
    public boolean DuCheck(List l, List allList){
        Iterator it = allList.iterator();
        while (it.hasNext()){
            List L = (List) it.next();
            if(CheckList(l,L)) return true;
        }
        return false;
    }

    /*
    *判断两个String类型的List是否完全相同
    *大小一样,所有元素互相含有,元素顺序可以不一致
    */
    //l1是l的形参,l2是allList中某个元素的形参
    boolean CheckList(List l1,List l2){

        if (l1 == l2) {
            return true;
        }
        if (l1 == null && l2 == null)
        {
            return true;
        }
        if (l1 == null || l2 == null)
        {
            return false;
        }
        if (l1.size() != l2.size())
        {
            return false;
        }
        if (l1.containsAll(l2) && l2.containsAll(l1))
        {
            return true;
        }

        return false;
    }
}

性能分析

内存占用情况

总体性能

测试

测试代码

public class test {
    @Test
    public void test1(){
        OperationPro.mainGenerate(10,10000);
    }
    @Test
    public void test2(){
        OperationPro.mainCheck("D:\\gitcode\\acofGDUT\\3121004921\\homework2\\Answer1.txt","D:\\gitcode\\acofGDUT\\3121004921\\homework2\\Answer.txt");
    }
    @Test
    public void test3(){
        getExpression getExpression = new getExpression();
        List exp = getExpression.getExp(new OperationExpression(null, null, null), 10);
        System.out.println(exp);
    }
    @Test
    public void test4(){
        getExpression getExpression = new getExpression();
        List exp = getExpression.getExp(new OperationExpression(null, null, null), 3);
        System.out.println(exp);
    }
    @Test
    public void test5(){
        Fraction a = new Fraction(true,6);
        Fraction b = new Fraction(true,6);
        System.out.println(a.sub(b));
    }
    @Test
    public void test6(){
        Fraction a = new Fraction(false,10);
        Fraction b = new Fraction(true,8);
        System.out.println(a.div(b));
    }
    @Test
    public void test7(){
        Fraction a = new Fraction(false,8);
        Fraction b = new Fraction(false,8);
        System.out.println(a.add(b));
    }
    @Test
    public void test8(){
        Fraction a = new Fraction(false,8);
        Fraction b = new Fraction(false,8);
        System.out.println(a.sub(b));
    }
    @Test
    public void test9(){
        System.out.println(CalculateService.prior("+", "-"));
    }
    @Test
    public void test10(){
        getExpression getExpression = new getExpression();
        List exp = getExpression.getExp(new OperationExpression(null, null, null), 3);
        System.out.println(CalculateService.toPostFix(exp));
    }

测试运行结果

覆盖率

文档生成情况


复制一份答案Answer1.txt 修改一部分答案,检查Grade文档

项目小结

龙新超:一起编写代码,我们能够迅速发现和纠正彼此的错误。这种实时反馈有助于提高代码质量,而且我学到了很多新知识,因为合作伙伴带来了不同的观点和经验。此外,我们在讨论设计和实现方案时能够做到更全面的思考,这也有助于我们制定更好的解决方案。
海尔江:两个人一起工作,能够共同解决问题,一起思考最佳实践,并发现彼此的盲点。这种协作方式加速了问题的诊断和解决,两个人互相交流和学习的经验也非常有价值。尽管在一开始可能感到有些不习惯,但我认为结对编程是一种提高代码质量和工作效率的重要实践。

标签:return,List,四则运算,生成器,Fraction,new,action,Java,public
From: https://www.cnblogs.com/ac4921/p/17732809.html

相关文章

  • JavaScript下载base64位文件
    1/**2*下载文件3**/4functiondownloadExcel(base64Data){5varmyBlob=this.base64toBlob(base64Data);6varmyUrl=URL.createObjectURL(myBlob);7varlink=document.createElement("a");8......
  • Java内值传递和引用传递记录
    不管哪个语言都有值传递,引用传递两种方式,在C语言里面引用传递用指针搞定。在Java里面没有指针,所以Java就规定(之前的设计)了某些类型是值传递,某些是引用传递,我这里不想一个一个写下来了,浪费时间,现在查AI那么方便的事。写程序的人,必须要知道两个概念。因为知道才是现在最重要的,怎么......
  • Java泛型简明解析:易懂但全面的介绍
    引言Java泛型的背景和作用Java泛型是Java编程语言中的一个特性,引入泛型的目的是为了增强代码的类型安全性和重用性。在没有泛型之前,Java中的集合类(如ArrayList、HashMap等)只能存储Object类型的对象,这使得在使用集合时需要进行强制类型转换,容易出现类型错误。泛型的背景:在Java5版本......
  • 使用CSS、HTML、JavaScript实现一个简单的身份验证页
      这是我在博客园的第一篇博客,也是我人生中的第一篇博客。希望它能够记录我的成长,帮助更多的人。  最近在写我们社团的社团网站,有一个页面不太希望普通访客能访问到,所以想做一个“统一身份验证验证”,但是又苦于社团网站搭建是纯静态站,没法做数据库,只能妥协,将账号密码字符串......
  • Java中线程间有哪些通信方式?
    1、volatile和synchronized关键字关键字volatile可以用来修饰字段(成员变量),就是告知程序任何对改变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性。关键字synchronized可以修饰方法或者以同步块的形式来进行使用,它主要确保......
  • Java中CornExpression说明
    关于cronExpression表达式有至少6个(也可能是7个)由空格分隔的时间元素,从左至右,这些元素约定义如下:1、秒(0~59)2、分(0~59)3、小时(0~23)4、月份中的日期(1-31)5、月份(1-12或JAN-DEC)6、星期中的日期(1-7或SUN-SAT)7、年份(1970-2099)eg:0010,14,16**?每天10点、14点、16点0015,30,45*......
  • java8基础镜像制作:基于官方镜像改编
    上次配完trivy之后,扫描java项目发现很多漏洞,具体分析了下,大部分居然是制作docker的基础镜像java:8造成的于是更新java8镜像就提上日程了,上dockerhub上看了下,最新版的java8镜像还是6年前。。无奈只能自己制作了,首先看一下当时java镜像的dockerfile ......
  • java使用标识符注意点
    标识符注意点所有的标识符都应该以字母(a-z/A-Z),美元符号($)或者下划线(_)开始.首字母之后可以用字母(a-z/A-Z),美元符号($)或者下划线(_)或数字的任何字符组合.不能使用关键字作为变量名或方法名标识符对大小写敏感,不能用错合法标识符演示:abc,$21,_dsa23非......
  • 基于Java开发的数字采购系统(供应商、询价、招标、订单送货)
    前言:随着互联网和数字技术的不断发展,企业采购管理逐渐走向数字化和智能化。数字化采购平台作为企业采购管理的新模式,能够提高采购效率、降低采购成本、优化供应商合作效率,已成为企业实现效益提升的关键手段。系统获取在文末。一、建设的必要性数字化采购平台是指利用互联网、......
  • 测试驱动技术(TDD)系列之3:详解Java数组
    在前面的文章中我介绍了如何通过junit4和TestNG实现参数化,这两种架构都通过二维数组来实现参数化,在这里我就给大家详细的介绍一下java数组。Junit4定义参数化数据,代码如下:publicstaticCollectionprepareData(){Object[][]object={{1,2,3},{0,2,2},{0,3,3}};returnArrays.as......