四则运算三
一、程序的设计思想
(1)查重
每三个元素划分为一组,来进行子表达式之间的查重,进行判断是否相同。
(2)数据库连接、释放
获取数据库连接的方法是将注册数据库驱动,获得一个数据库的连接进行封装,返回一个数据库连接对象;另外,释放资源的方法是将释放查询数据库结果集对象、数据库操作对象和数据库连接对象进行封装。
二、源程序代码
package hh;
import java.util.Random;
import java.util.Scanner;
import java.util.Stack;
//分数类
class fraction {
public int fenMu,fenZi;
public int getFenMu() {
return fenMu;
}
public void setFenMu(int fenMu) {
this.fenMu = fenMu;
}
public int getFenZi() {
return fenZi;
}
public void setFenZi(int fenZi) {
this.fenZi = fenZi;
}
public fraction(int fenMu, int fenZi) {
this.fenMu = fenMu;
this.fenZi = fenZi;
yueFen();
}
public fraction(){}
//找出两数的最大公约数
public int MaxCommon(int a,int b){
//保证第一个参数大于第二个参数
if(a<b)
{
int temp;
temp=a;
a=b;
b=temp;
}
while(a%b!=0) //在余数不为零时循环
{
int temp=a%b;
a=b;
b=temp;
}
return b; //返回最大公约数
}
//找出两数的最小公倍数
public int MinCommon(int a,int b){
return a*b/MaxCommon(a,b);
}
//约分化简
public void yueFen(){
int y = 1;
for(int i = fenZi;i > 1;i--){
if(fenZi % i == 0 && fenMu % i == 0){
y = i;
break;
}
}
fenZi /= y;
fenMu /= y;
}
//计算(加)
public fraction add(fraction b){
fraction c = null;
int newFenZi = this.fenZi * b.getFenMu() + this.fenMu * b.getFenMu();
int newFenMu = this.fenMu * b.getFenMu();
c = new fraction(newFenMu,newFenZi);
return c;
}
//计算(减)
public fraction subtract(fraction b){
fraction c = null;
int newFenZi = this.fenZi * b.getFenMu() - this.fenMu * b.getFenZi();
int newFenMu = this.fenMu * b.getFenMu();
c = new fraction(newFenMu,newFenZi);
return c;
}
//计算(乘)
public fraction multiply(fraction b){
fraction c = null;
int newFenZi = this.fenZi * b.getFenZi();
int newFenMu = this.fenMu * b.getFenMu();
c = new fraction(newFenMu,newFenZi);
return c;
}
//计算(除)
public fraction divide(fraction b){
fraction c = null;
int newFenZi = this.fenZi * b.getFenMu();
int newFenMu = this.fenMu * b.getFenZi();
c = new fraction(newFenMu,newFenZi);
return c;
}
//输出分数形式
public String toString(){
if(fenZi != 0){
return fenZi + "/" + fenMu;
}
return "0";
}
}
public class kk {
public static String[] Answer=new String[100];
//生成整数计算式添加限制条件,type为运算式类型 0代表整数式,1代表真分数式
public static String[] createYunSuanShi(int hasChengChu,int hasKuoHao,int hasFuShu,int hasYuShu,int minNum,int maxNum,int n,int type) {
int i = 0;
int z = 0;
String yunSuanShiTemp;
String[] yunSuanShiArray = new String[n];
int operatorScope = 2 + 2 * hasChengChu;//运算符范围,2或4,2代表只有加减,4代表有加减乘除
int length;
String[] operatorArray = {"+","-","*","/"};
String[] operatorNum = null;//存储运算数
int num_index;//运算数下标
String[] operatorSymbol = null;//存储运算符
int symbol_index;//运算符下标
int[] brackets = null;//存储括号个数
while(i < n) {
length = Integer.parseInt(getOperatorNumber(0, 0,9)) + 2;//计算式运算数长度
operatorNum = new String[length];
operatorSymbol = new String[length - 1];
num_index = 0;
symbol_index = 0;
operatorNum[num_index++] = getOperatorNumber(type,minNum, maxNum);//随机生成操作数
for(int j = 0;j < length - 1;j++){
operatorSymbol[symbol_index++] = operatorArray[Integer.parseInt(getOperatorNumber(0,0,operatorScope-1))];//随机生成操作符
operatorNum[num_index++] = getOperatorNumber(type, minNum,maxNum);//随机生成操作数
}
if(hasKuoHao == 1){
brackets = randomAddBracket(length);//生成括号数组
}
//构造运算式
yunSuanShiTemp = "";
for(int j = 0;j < length;j++){
//添加左括号
if(hasKuoHao == 1){
for(int k = 0;k < brackets[j];k++){
yunSuanShiTemp += "(";
}
}
yunSuanShiTemp += " " + operatorNum[j] + " ";//加上运算数
//添加右括号
if(hasKuoHao == 1){
for(int k = 0;k > brackets[j];k--){
yunSuanShiTemp += ")";
}
}
//如果不是最后一个运算数则要加上运算符
if(j != length - 1){
yunSuanShiTemp += operatorSymbol[j];
}
}
//计算结果
String answer = expressCalculate(yunSuanShiTemp, hasFuShu, hasYuShu, type, length - 1);
if((answer.equals("ERROR"))){
continue;
}
yunSuanShiTemp += "=" /*+ answer*/;
Answer[z]=answer;
z++;
//检验重复
boolean chongFu = false;
for(int j = 0;j < i;j++){
if((yunSuanShiArray[j].equals(yunSuanShiTemp))){
chongFu = true;
break;
}
}
if(chongFu == false){
yunSuanShiArray[i++] = yunSuanShiTemp;
}
}
return yunSuanShiArray;
}
//表达式计算,参数为字符串类型的运算式
public static String expressCalculate(String express,int hasFuShu,int hasYuShu,int type,int symbolNum){
Stack<String> num = new Stack<String>();
Stack<String> symbolS = new Stack<String>();
symbolS.push("#");
express += "#";
char ch;
int i = 0;
int s = 0;
ch = express.charAt(i);
while(s < symbolNum){
if(ch == ' '){//读到空格,说明开始读运算数
String readNumStr = "";
while(true){
ch = express.charAt(++i);
if(ch == ' '){
break;
}
readNumStr += ch;
}
if((i + 1) < express.length()){
ch = express.charAt(++i);
}
num.push(readNumStr);
}else{//读到的是运算符
char compare = priorityCompare(symbolS.peek(),ch + "");
if(compare == '='){//如果是右括号
symbolS.pop();
ch = express.charAt(++i);
}else if(compare == '>'){//ch的优先级小于栈顶的优先级 比栈顶的优先级高就不算,入栈,低就弹栈运算
//弹出两个运算数,弹出一个运算符
String bStr = num.pop();
String aStr = num.pop();
String symbolT = symbolS.pop();
String c = yunSuan(aStr,bStr,symbolT,hasFuShu,hasYuShu,type);
if(c.equals("ERROR")){
return "ERROR";
}else if(c.indexOf("余") >= 0 && s != symbolNum - 1){//有余数
return "ERROR";
}else{
num.push(c);
}
s++;
}else{
symbolS.push(ch + "");
if((i + 1) < express.length()){
ch = express.charAt(++i);
}
}
}
}
return num.pop();
}
public static String yunSuan(String aStr,String bStr,String symbol,int hasFuShu,int hasYuShu,int type){
if(type == 0){//整数
int a = Integer.parseInt(aStr);
int b = Integer.parseInt(bStr);
if(symbol.equals("+")){
return "" + (a + b);
}else if(symbol.equals("-")){
if(a - b < 0 && hasFuShu == 0){
return "ERROR";
}else{
return "" + (a - b);
}
}else if(symbol.equals("*")){
return "" + (a * b);
}else{
if(b == 0){
return "ERROR";
}
if(a % b == 0){
return "" + (a / b);
}else{
if(hasYuShu == 1){
return (a / b) + "余" + (a % b);
}else{
return "ERROR";
}
}
}
}else{//分数
String[] af = aStr.split("/");
String[] bf = bStr.split("/");
if(af[0].equals("0") || bf[0].equals("0")){
return "ERROR";
}
fraction a = new fraction(Integer.parseInt(af[1]),Integer.parseInt(af[0]));
fraction b = new fraction(Integer.parseInt(bf[1]),Integer.parseInt(bf[0]));
if(symbol.equals("+")){
return a.add(b).toString();
}else if(symbol.equals("-")){
fraction c = a.subtract(b);
if(hasFuShu == 1 && c.getFenZi() < 0){
return "ERROR";
}
return c.toString();
}else if(symbol.equals("*")){
return a.multiply(b).toString();
}else{
return a.divide(b).toString();
}
}
}
//判断优先级
public static char priorityCompare(String a,String b){
char[][] priority = {
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','>'},
{'>','>','>','>',' ','>','>'},
{'<','<','<','<','<',' ','='}
};
int a_index = index_symbol(a);
int b_index = index_symbol(b);
return priority[a_index][b_index];
}
public static int index_symbol(String a){
String p = "+-*/()#";
return p.indexOf(a);
}
//随机生成括号,参数为运算式的运算数的个数
public static int[] randomAddBracket(int length){
int[] brackets = new int[length];
for(int i = 0;i < brackets.length;i++) brackets[i] = 0;
Random rd = new Random();
for(int i = 2;i < length;i++){//添加的括号长度(括号包围的运算数的个数)
for(int j = 0;j < length - i + 1;j++){
int t = rd.nextInt(2);//随机生成0或1,0代表不加括号,1代表加括号
if(t == 1){
if(brackets[j] >= 0 && brackets[j + i - 1] <= 0){//要加的括号的第一个运算数周围没有右括号,且 最后一个运算数周围没有左括号
int counteract = 0;
for(int k = j;k < j + i;k++){//将要加的括号之间的所有运算数对应的brackets相加,
//如果和为0说明这个括号之间的括号是匹配的,不会出现括号交叉现象
counteract += brackets[k];
}
if(counteract == 0){
brackets[j]++;
brackets[j + i - 1]--;
}
}
}
}
}
return brackets;
}
//随机生成一个运算数( type==0代表生成整数,type==1代表生成真分数,maxNum代表数值范围 0-(maxNum-1) )
public static String getOperatorNumber(int type,int minNum,int maxNum){
Random rd = new Random();
int a,b;
while(true){
a = rd.nextInt(maxNum-minNum+1)+minNum;
if(type == 0){//随机生成一个整数
return "" + a;
}else{//随机生成一个真分数
if(a == 0){
continue;
}
b = rd.nextInt(maxNum-minNum+1)+minNum;
System.out.println(b);
while(b>=a)
{
b = rd.nextInt(maxNum-minNum+1)+minNum;
if(a>b)
{
break;
}
}
System.out.println(b);
fraction c = new fraction(a,b);
return c.toString();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
System.out.print("请输入所要生成题目的数目:");
int n = sc.nextInt();
System.out.print("请输入: 0、整数式 ; 1、分数式:");
int type = sc.nextInt();
System.out.print("是否有乘除法?(1有,0没有):");
int hasChengChu = sc.nextInt();
System.out.print("是否有括号?(1有,0没有):");
int hasKuoHao = sc.nextInt();
System.out.print("加减有无负数?(1有,0没有):");
int hasFuShu = sc.nextInt();
System.out.print("除法有无余数?(1有,0没有):");
int hasYuShu = sc.nextInt();
System.out.print("数值范围(最小数):");
int minNum = sc.nextInt();
System.out.print("数值范围(最大数):");
int maxNum = sc.nextInt();
String[] yunSuanShiArray = createYunSuanShi(hasChengChu, hasKuoHao, hasFuShu, hasYuShu,minNum, maxNum, n, type);
for(int i = 0;i < yunSuanShiArray.length;i++){
System.out.print(yunSuanShiArray[i]);
String result=sc.next();
if(result.equals(Answer[i])){
System.out.print(" 回答正确!");
}
else{
System.out.print(" 回答错误!"+"正确答案为:"+Answer[i]);
}
System.out.println();
}
sc.close();
}
}
三、运行结果截图
四、编程总结分析
下星期的编程任务应该是改为web版,这一星期的编程时间并不是特别长,所以下个星期应该更加努力去完善程序,争取早日完成这个程序!数据库之前连接的不太顺利,是由于列名与程序中的sql语句不对应导致。
五、个人收获
通过此次程序的编写,使得我掌握了数据库的创建,以及在程序中对数据库的使用,将四则运算加减乘除的算法得以编译,掌握了乘除中所得结果的约简算法,css简单样式的设计。