可定制的算式生成器(老师定制小学生练习题)

    科技2024-09-27  17

    可定制的算式生成器

    具体可定制内容

    算式个数是否有乘除法结果集数值范围加减法有无负数除法又无余数除法出现小数是否支持分数显示选择需要算术输入的文件打印每行个数

    本人喜欢沉浸代码之中,耗时好几个小时,由于是自己写的,所以注释较少,思路较为简单

    话不多说,先上运行成果

    请输入需要算式个数: 100 请输入需要乘除法(Y/N): y 请输入需要结果集范围(默认-n~n): 99 请输入允许加减法出现负数(Y/N): y 请输入允许除法出现小数(Y/N): y 请输入允许除法结果换算成分数(Y/N): y 请输入算式每行个数: 5 请输入算式需要导入的文件名: test1 定制完成,正在随机生成算式。。。。 算式生成成功,耗时6毫秒! 已成功将算式保存到test1.txt中,答案保存到test1_Answer.txt中,欢迎您的下次使用!

    如果符合您的要求继续看,不符合直接移步(就是这么豪横😁)

    思路

    首先写接口将自己需要的接口一口气写出(就是这么莽),然后后期进行补录。使用Map将算式封装及其方便代码全部在本文中,创建普通java项目即可运行(唯一需要注意的就是文件目录可能需要根据个人创建项目名称进行更改)程序目录结构:

    IFormulaGeneration

    package cn.zhl.software; import java.util.Map; public interface IFormulaGeneration { //加法生成接口,结果范围,加法有无负数,生成个数 public Map<String,Integer> Add(int resultRange,boolean is,int num); //减法生成接口,结果范围,减法有无负数,生成个数 public Map<String,Integer> Sub(int resultRange,boolean is,int num); //乘法生成接口,生成个数 public Map<String,Integer> Mul(int resultRange,int num); //除法生成接口,结果范围,除法有无余数,是否支持分数,生成个数 public Map<String,String> Div(int resultRange,boolean is,boolean is2,int num); //检测算式是否存在重复,如果存在返回true public boolean Repeat(Map<?,?> map,String formula); //生成特定范围的数值 public int nextInt(int min, int max); //化简小数 public String fracReduction(int numerator, int denominator); //算法生成器:算式个数,是否有乘除法,数值范围,加减法有无负数,除法又无余数,是否支持分数,打印每行个数 public Map<String,?> FormulaCustom(int formulaNum,boolean if_MulDiv,int range, boolean ifNeg_AddSub,boolean ifRem_Div, boolean ifRed_Div,int lineNum); } 然后编写实现类(还没养成编写代码边注释的习惯,查看接口可了解各个函数功能) FormulaRealization package cn.zhl.software; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.Set; public class FormulaRealization implements IFormulaGeneration { Random random = new Random(); @Override public Map<String, Integer> Add(int resultRange, boolean is, int num) { if (resultRange < 0) { resultRange = -resultRange; } Map<String, Integer> addMap = new HashMap<>(); int r1 = 0, r2 = 0, n = 0; String formula = ""; for (; n < num; ) { r1 = nextInt(-resultRange, resultRange); if (is) {//加法允许出现负数 r2 = nextInt(-resultRange - r1, resultRange - r1); } else { r2 = nextInt(-r1, resultRange - r1); } formula = (r1 < 0 ? "(" + r1 + ")" : r1) + "+" + (r2 < 0 ? "(" + r2 + ")" : r2); if (Repeat(addMap, formula)) { addMap.put(formula, r1 + r2); n++; } } return addMap; } @Override public Map<String, Integer> Sub(int resultRange, boolean is, int num) { if (resultRange < 0) { resultRange = -resultRange; } Map<String, Integer> subMap = new HashMap<>(); int r1 = 0, r2 = 0, n = 0; String formula = ""; for (; n < num; ) { r1 = nextInt(-resultRange, resultRange); if (is) {//加法允许出现负数 r2 = nextInt(-resultRange + r1, resultRange + r1); } else { r2 = nextInt(r1, resultRange + r1); } formula = (r1 < 0 ? "(" + r1 + ")" : r1) + "-" + (r2 < 0 ? "(" + r2 + ")" : r2); if (Repeat(subMap, formula)) { subMap.put(formula, r1 - r2); n++; } } return subMap; } @Override public Map<String, Integer> Mul(int resultRange, int num) { if (resultRange == 0) { resultRange = 1; } if (resultRange < 0) { resultRange = -resultRange; } Map<String, Integer> mulMap = new HashMap<>(); int r1 = 0, r2 = 0, n = 0; String formula = ""; for (; n < num; ) { while (r1 == 0) { r1 = nextInt(-resultRange, resultRange); } r2 = nextInt(-(int) (resultRange / Math.abs(r1)), (int) (resultRange / Math.abs(r1))); formula = (r1 < 0 ? "(" + r1 + ")" : r1) + "*" + (r2 < 0 ? "(" + r2 + ")" : r2); if (Repeat(mulMap, formula)) { mulMap.put(formula, r1 * r2); n++; r1 = nextInt(-resultRange, resultRange); } } return mulMap; } @Override public Map<String, String> Div(int resultRange, boolean is, boolean is2, int num) { if (resultRange == 0) { resultRange = 1; } if (resultRange < 0) { resultRange = -resultRange; } Map<String, String> divMap = new HashMap<>(); int r1 = 0, r2 = 0, n = 0; String formula = ""; for (; n < num; ) { //r1 = nextInt(-resultRange, resultRange); while (r2 == 0) { r2 = nextInt(-resultRange, resultRange); } if (!is) {//除法没有余数 r1 = r2 * nextInt(-(resultRange), resultRange); } else {//有余数 r1 = nextInt(-resultRange, resultRange); } formula = (r1 < 0 ? "(" + r1 + ")" : r1) + "/" + (r2 < 0 ? "(" + r2 + ")" : r2); if (Repeat(divMap, formula)) { String result = ""; if (is && is2) {//有余数且化为分数 if(r1*r2<0){ result = "-"+fracReduction(Math.abs(r1), Math.abs(r2)); }else { result = fracReduction(Math.abs(r1), Math.abs(r2)); } if(r1%r2==0){ result = ((double) r1 / r2) + ""; } } else { if (!is) {//无余数 result = ((double) r1 / r2) + ""; } if (is) { result = ((double) r1 / r2) + ""; } } if(r1==0){ result=0.0+""; } if (r1==-r2){ result="-1.0"; } divMap.put(formula, result); n++; } } return divMap; } @Override public boolean Repeat(Map<?, ?> map, String formula) { if (map.isEmpty()) { return true; } else { Set<String> strings = (Set<String>) map.keySet(); for (String string : strings) { //如果当前算式与前面算式重复返回false if (string.equals(formula)) { return false; } } //如果当前算式与前面算式不存在重复返回true return true; } } @Override public int nextInt(int min, int max) { if (min == max) { return max; } return random.nextInt(max - min + 1) + min; } @Override public String fracReduction(int numerator, int denominator) { //找到最大公约数,然后分别处以最大公约数 int m = numerator; int n = denominator; int r; while (numerator > 0) { r = denominator % numerator; denominator = numerator; numerator = r; } // if ((m / denominator)==-(n / denominator)){ // return "-1.0"; // } return m / denominator + "/" + n / denominator; } @Override //算法生成器:算式个数,是否有乘除法,数值范围,加减法有无负数,除法又无余数,是否支持分数,打印每行个数 public Map<String, ?> FormulaCustom(int formulaNum, boolean if_MulDiv, int range, boolean ifNeg_AddSub, boolean ifRem_Div, boolean ifRed_Div, int lineNum) { int add = 0, sub = 0, mul = 0, div = 0; add = nextInt(formulaNum/5,formulaNum/3); sub = nextInt((formulaNum - add)/4,(formulaNum - add)/2); mul = nextInt((formulaNum - add - sub)/3,(formulaNum - add - sub)/1); div = formulaNum - add - sub - mul; Map map = new HashMap(); if (if_MulDiv) {//如果存在乘除法将算式总数分为四份 Map<String, Integer> addMap = Add(range, ifNeg_AddSub, add); Map<String, Integer> subMap = Sub(range, ifNeg_AddSub, sub); Map<String, Integer> mulMap = Mul(range, mul); Map<String, String> divMap = Div(range, ifRem_Div, ifRed_Div, div); map.putAll(addMap); map.putAll(subMap); map.putAll(mulMap); map.putAll(divMap); } else {//不存在则分为两份 Map<String, Integer> addMap = Add(range, ifNeg_AddSub, add); Map<String, Integer> subMap = Sub(range, ifNeg_AddSub, sub); map.putAll(addMap); map.putAll(subMap); } return map; } } 编写测试类进行功能测试(这一步是与编写实现类同步进行的) FormulaRealizationTest package cn.zhl.test; import cn.zhl.software.FormulaRealization; import org.junit.Test; import java.util.Map; import java.util.Set; public class FormulaRealizationTest { FormulaRealization formulaRealization = new FormulaRealization(); @Test public void testAdd() { Map<String, Integer> add = formulaRealization.Add(100, false, 5); for (String s : add.keySet()) { System.out.print(s+"="+add.get(s)+" "); } } @Test public void testSub() { Map<String, Integer> sub = formulaRealization.Sub(100, true, 5); for (String s : sub.keySet()) { System.out.print(s+"="+sub.get(s)+" "); } } @Test public void testMul() { Map<String, Integer> mul = formulaRealization.Mul(100, 5); for (String s : mul.keySet()) { System.out.print(s+"="+mul.get(s)+" "); } } @Test public void testDiv() { Map<String, String> div = formulaRealization.Div(100, true, true, 5); for (String s : div.keySet()) { System.out.print(s+"="+div.get(s)+" "); } } @Test public void test1() { String div = formulaRealization.fracReduction(25,5); System.out.print(div); } } 考虑到将数据持久化,想到用文件存储(小小的程序用数据库反而更麻烦)首先文件接口 IFileGeneration package cn.zhl.fileCreate; import java.util.Map; public interface IFileGeneration { //用于将产生的算式写入到文件中 public void fileShow(Map<String,?> stringMap,int lineNum,String fileName); } 然后实现类 FileRealization package cn.zhl.fileCreate; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Map; public class FileRealization implements IFileGeneration { @Override public void fileShow(Map<String,?> stringMap, int lineNum, String fileName) { int n=0; String answerName=fileName+"_Answer.txt"; fileName=fileName+".txt"; /*File file1 = new File("\\cn\\zhl\\formulaFile\\" + fileName); File file2 = new File("\\cn\\zhl\\formulaFile\\" + answerName);*/ File file1 = new File("Arithmetic_question_generation_system\\src\\cn\\zhl\\formulaFile\\"+fileName); File file2 = new File("Arithmetic_question_generation_system\\src\\cn\\zhl\\formulaFile\\"+answerName); for (String s : stringMap.keySet()) { n++; try(FileWriter formulaWriter = new FileWriter(file1,true); FileWriter answerWriter = new FileWriter(file2,true)) { formulaWriter.write(s+"= "); answerWriter.write(s+"="+stringMap.get(s)+" "); if(n%lineNum==0){ formulaWriter.write("\n"); answerWriter.write("\n"); } } catch (IOException e) { e.printStackTrace(); System.out.println("未成功将算式保存到"+fileName+"中,答案保存到"+answerName+"中,请联系开发人员!"); } } System.out.println("已成功将算式保存到"+fileName+"中,答案保存到"+answerName+"中,欢迎您的下次使用!"); } } 一切准备就绪,编写主函数,将数据填充就大功告成喽

    FormulaCustomTest

    package cn.zhl.software; import cn.zhl.fileCreate.FileRealization; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Map; import java.util.Scanner; public class FormulaCustomTest { public static void main(String[] args) { int formulaNum; boolean if_MulDiv;int range; boolean ifNeg_AddSub;boolean ifRem_Div; boolean ifRed_Div;int lineNum; Scanner scanner = new Scanner(System.in); System.out.println("请输入需要算式个数:"); formulaNum=scanner.nextInt(); System.out.println("请输入需要乘除法(Y/N):"); if(scanner.next().equals("y")||scanner.next().equals("Y")){ if_MulDiv=true; }else { if_MulDiv=false; } System.out.println("请输入需要结果集范围(默认-n~n):"); range=scanner.nextInt(); System.out.println("请输入允许加减法出现负数(Y/N):"); if(scanner.next().equals("y")||scanner.next().equals("Y")){ ifNeg_AddSub=true; }else { ifNeg_AddSub=false; } System.out.println("请输入允许除法出现小数(Y/N):"); if(scanner.next().equals("y")||scanner.next().equals("Y")){ ifRem_Div=true; }else { ifRem_Div=false; } System.out.println("请输入允许除法结果换算成分数(Y/N):"); if(scanner.next().equals("y")||scanner.next().equals("Y")){ ifRed_Div=true; }else { ifRed_Div=false; } System.out.println("请输入算式每行个数:"); lineNum=scanner.nextInt(); //文件名 String fileName=""; System.out.println("请输入算式需要导入的文件名:"); fileName=scanner.next(); System.out.println("定制完成,正在随机生成算式。。。。"); long l = System.currentTimeMillis(); //算法生成器:算式个数,是否有乘除法,数值范围,加减法有无负数,除法又无余数,是否支持分数,打印每行个数 FormulaRealization formulaRealization = new FormulaRealization(); Map<String, ?> stringMap = formulaRealization.FormulaCustom(formulaNum,if_MulDiv,range, ifNeg_AddSub,ifRem_Div, ifRed_Div,lineNum); long l2 = System.currentTimeMillis(); System.out.println("算式生成成功,耗时"+(l2-l)+"毫秒!"); FileRealization fileRealization = new FileRealization(); fileRealization.fileShow(stringMap,lineNum,fileName); } }

    运行结果

    请输入需要算式个数: 100 请输入需要乘除法(Y/N): y 请输入需要结果集范围(默认-n~n): 99 请输入允许加减法出现负数(Y/N): y 请输入允许除法出现小数(Y/N): y 请输入允许除法结果换算成分数(Y/N): y 请输入算式每行个数: 5 请输入算式需要导入的文件名: test1 定制完成,正在随机生成算式。。。。 算式生成成功,耗时6毫秒! 已成功将算式保存到test1.txt中,答案保存到test1_Answer.txt中,欢迎您的下次使用!

    test1.txt

    (-58)*1= 29+(-41)= (-75)*(-1)= 95-145= (-28)/82= 76/82= (-52)*(-1)= (-31)+97= (-87)-(-130)= (-38)/82= 35/82= 60+(-68)= (-56)/82= (-42)-(-57)= 10/82= (-99)/82= (-20)-(-3)= (-26)/82= 42*(-1)= 47-128= 45+49= (-82)+122= (-29)*0= 96*1= 88*(-1)= (-80)-(-134)= 81+(-9)= 17/82= 69*0= (-68)/82= (-89)-(-164)= 13+(-57)= 70+(-29)= (-81)*0= (-34)*(-1)= 34-(-38)= (-78)-(-5)= 12/82= 85/82= 94+(-79)= 75-16= 11*1= (-49)/82= 74/82= 83-21= 26/82= 95*(-1)= (-46)-(-111)= 90*0= 15*(-1)= (-45)/82= (-77)*1= (-70)+160= (-23)*(-2)= 14+(-16)= (-71)*(-1)= 77*(-1)= (-14)*(-7)= 60*0= 36-107= 34+(-16)= 41*1= 26*0= 30+(-74)= 46+(-45)= (-74)*1= (-57)*0= (-23)-23= (-2)*(-6)= 79*0= 58-28= 38-(-27)= (-14)/82= (-19)-(-17)= 38+(-123)= 43-19= (-47)+(-47)= (-69)+50= 7/82= 3*24= 11*(-9)= (-46)-(-137)= 6-105= 48*0= (-33)/82= 80-84= (-84)-1= (-5)*(-16)= 90*(-1)= 89/82= (-56)+152= 5-(-51)= 50/82= 95/82= (-71)/82= (-94)+54= 64/82= 53+(-64)= 81/82= 26*(-3)=

    test1_Answer.txt

    (-58)*1=-58 29+(-41)=-12 (-75)*(-1)=75 95-145=-50 (-28)/82=-14/41 76/82=38/41 (-52)*(-1)=52 (-31)+97=66 (-87)-(-130)=43 (-38)/82=-19/41 35/82=35/82 60+(-68)=-8 (-56)/82=-28/41 (-42)-(-57)=15 10/82=5/41 (-99)/82=-99/82 (-20)-(-3)=-17 (-26)/82=-13/41 42*(-1)=-42 47-128=-81 45+49=94 (-82)+122=40 (-29)*0=0 96*1=96 88*(-1)=-88 (-80)-(-134)=54 81+(-9)=72 17/82=17/82 69*0=0 (-68)/82=-34/41 (-89)-(-164)=75 13+(-57)=-44 70+(-29)=41 (-81)*0=0 (-34)*(-1)=34 34-(-38)=72 (-78)-(-5)=-73 12/82=6/41 85/82=85/82 94+(-79)=15 75-16=59 11*1=11 (-49)/82=-49/82 74/82=37/41 83-21=62 26/82=13/41 95*(-1)=-95 (-46)-(-111)=65 90*0=0 15*(-1)=-15 (-45)/82=-45/82 (-77)*1=-77 (-70)+160=90 (-23)*(-2)=46 14+(-16)=-2 (-71)*(-1)=71 77*(-1)=-77 (-14)*(-7)=98 60*0=0 36-107=-71 34+(-16)=18 41*1=41 26*0=0 30+(-74)=-44 46+(-45)=1 (-74)*1=-74 (-57)*0=0 (-23)-23=-46 (-2)*(-6)=12 79*0=0 58-28=30 38-(-27)=65 (-14)/82=-7/41 (-19)-(-17)=-2 38+(-123)=-85 43-19=24 (-47)+(-47)=-94 (-69)+50=-19 7/82=7/82 3*24=72 11*(-9)=-99 (-46)-(-137)=91 6-105=-99 48*0=0 (-33)/82=-33/82 80-84=-4 (-84)-1=-85 (-5)*(-16)=80 90*(-1)=-90 89/82=89/82 (-56)+152=96 5-(-51)=56 50/82=25/41 95/82=95/82 (-71)/82=-71/82 (-94)+54=-40 64/82=32/41 53+(-64)=-11 81/82=81/82 26*(-3)=-78

    不足

    对输入的数据没有进行非法检测加加减乘除有很多重复代码没有对重复代码进行封装
    Processed: 0.012, SQL: 8