标签:
实现功能:
1.整数和真分数的四则运算, 运算数和运算结果都可以是整数或分数;
2.能生成任意个运算数的算式(不超过100);
3.算式的个数、数的范围、运算数的个数由命令行输入;
4.不支持括号。
实现思路:
1.定义算式类,数据成员包含两个数组,分别存储运算数和算符;以及算式的结果;
方法成员包括一个初始化函数,随机生成算式并计算结果;一个输出函数,用来打印算式;以及其他辅助函数。
2.定义运算数类,数据成员包含两个整数,即分子和分母。
3.在主类里调用算式类的方法,来生成和输出算式;接受用户输入并判断正误。
结果截图:
程序代码:
主类Week1:
import java.util.Scanner;
public class Week1 {
public static void main (String args[]) {
Scanner scan = new Scanner(System.in);
question q = new question(); //创建一个算式的实例
int r = Integer.parseInt(args[0]); //运算数的范围,由命令行输入
int n = Integer.parseInt(args[1]); //算式的数量,由命令行输入
int l = Integer.parseInt(args[2]); //运算数的个数,由命令行输入
int count = 0; //用户答对的题数
for (int i = 0; i < n; i ++ ) {
q.initialize(r,l); //随机生成算式
q.print(l); //将算式打印到屏幕上
if (scan.nextLine().equals (q.res)) { //接受用户输入的答案并判断正误
System.out.println("回答正确!\n");
count ++;
}
else {
System.out.println("回答错误! 正确答案是: " + q.res + "\n");
}
}
//输出分数
System.out.println("您答对了" + count + "道题目,得分:" + 100 * count / n + "!\n");
scan.close();
}
}
运算数类number:
/*操作数类的定义*/
public class number {
int n; //分子
int d; //分母
}
算式类question:
import java.util.Stack;
/*算式类的定义*/
public class question {
char opr[] = {‘+‘,‘-‘,‘*‘,‘/‘}; //四则运算符
number oprd[] = new number[100]; //存储运算数的数组
char op[] = new char [100]; //存储运算符的数组
number result = new number(); //运算结果
String res; //运算结果的字符串形式
/*算式类的构造函数:随机生成运算数和算符,并计算出结果*/
public void initialize (int r, int l) { //参数r是运算数的范围, l是运算数的个数
int i,j;
//随机生成算式
for (i = 0; i < l; i++) { //随机生成运算数
oprd[i] = new number();
oprd[i].d = (int) (Math.random() * r) + 1; //分子
oprd[i].n = (int) (Math.random() * (oprd[i].d-1)) + 1; //分母
yf(oprd[i]); //约分
}
for (i = 0; i < l-1; i++) { //随机生成运算符
op[i] = opr[(int) (Math.random() * 4)];
}
op[l-1] = ‘=‘;
//计算该算式的结果
Stack <Character> operator = new Stack <Character>(); //运算符栈
Stack <number> operand = new Stack <number>(); //运算数栈
number x = new number(), y = new number(), z = new number();
i = j = 0;
while (true) { //扫描栈
operand.push(oprd[i++]); //运算数入栈
if (j == l-1) break; //所有运算符已入栈,则停止扫描
//如果当前运算符的优先级较低
while (!operator.isEmpty() && PRI(op[j]) <= PRI(operator.peek())) {
y = operand.pop(); //两个运算数出栈
x = operand.pop();
z = solve (x, y, operator.pop()); //运算符出栈,计算
operand.push(z); //结果入栈
}
operator.push(op[j++]); //直接入栈
}
while (operand.size() != 1) { //清空栈,直到运算数栈只剩最后一个数,即结果
y = operand.pop(); //两个运算数出栈
x = operand.pop();
z = solve (x, y, operator.pop()); //运算符出栈,计算两个运算数的结果
operand.push(z); //结果入栈
}
result = operand.pop(); //运算数栈底元素为最终结果
//运算结果转换成字符串
if (result.n == 0) res = String.valueOf(0); //结果为0
else if (result.d == 1) res = String.valueOf(result.n); //结果为整数
else res = String.valueOf(result.n) + ‘/‘ + String.valueOf(result.d); //结果为分数
}
/*求两运算数表达式的值*/
public number solve (number x, number y, char op) {
number t1 = new number(), t2 = new number();
int lcm = LCM (x.d, y.d);
t1.n = x.n * lcm / x.d; //将两数通分
t2.n = y.n * lcm / y.d;
t1.d = t2.d = lcm;
switch (op) { //计算结果
case ‘+‘:
t1.n += t2.n;
break;
case ‘-‘:
t1.n -= t2.n;
break;
case ‘*‘:
t1.n = x.n * y.n;
t1.d = x.d * y.d;
break;
case ‘/‘:
t1.n = x.n * y.d;
t1.d = x.d * y.n;
break;
default:
break;
}
yf (t1); //将结果进行约分
return t1;
}
/*计算运算符的优先级*/
public int PRI (char c) {
if (c == ‘+‘ || c == ‘-‘) return 0; //加减优先级较低
else if (c == ‘*‘ || c == ‘/‘) return 1; //乘除优先级较高
else return -1; //其他情况
}
/*输出算式*/
public void print (int l) {
String exp = new String();
for (int i = 0; i < l; i ++) {
if (oprd[i].d == 1) exp += String.valueOf(oprd[i].n); //整数
else exp += String.valueOf(oprd[i].n) + ‘/‘ + String.valueOf(oprd[i].d); //分数
exp += " " + op[i] + " ";
}
System.out.println(exp);
}
/*求最大公约数*/
public int GCD (int a, int b) {
int gcd = 1;
for (int i = 1; i <= a; i ++) {
if (a % i == 0 && b % i == 0) {
gcd = i;
}
}
return gcd;
}
/*求最小公倍数*/
public int LCM (int a, int b) {
return a * b / GCD(a,b);
}
/*对分数进行约分*/
public void yf (number p) {
int gcd = GCD (p.d, p.n);
p.d /= gcd;
p.n /= gcd;
}
}
标签:
原文地址:http://www.cnblogs.com/EverBlue/p/5907610.html