任务04
版本回退及创建分支
- 版本回退
参考Git和Github简单教程中对git部分命令的介绍,对版本进行回退。- git log查看当前代码仓库中的版本,可以看到各个版本的版本号(黄色 commit开头的)。
- git reset --hard xxxx回退到任务2的版本,XXXX区版本号前7位,版本号在上一步可见。
- 此时git log会发现任务2之后的版本消失,可用git reflog找到还原前的版本号。
- 创建分支
参考[[git] git 分支( branch ) 的基本使用 ]([git] git 分支( branch ) 的基本使用 )- git branch 分支名 创建新分支(不会切换到新分支)。
- git checkout 分支名 切换到该分支。
修改任务2的四则运算
对任务2的四则运算进行如下修改:
- 生成的算式中的运算数必须为自然数(0、1、2……)或真分数(1/2、4/5 等分子比分母小的分数)。
- 乘号用 × 表示;除号用 ÷ 表示,代替 / 号。
- 算式中,运算符与运算数之间必须加空格,但若是分数形式,则不需要,如:3 + 1/2 。
- 能随机生成 2~3 个运算符的算式,如:2 + 3 * 4 ,注意此算式的答案也必须按照运算优先级进行计算。
- 能生成带括号的算式,如 (2 + 3) * 4 和 3 / (4 + 2)。括号的运算优先级要高于加减乘除。
- 在用户输入答案后,除显示对错之外,还需要显示此题的正确答案。
生成的算式中的运算数必须为自然数(0、1、2……)或真分数(1/2、4/5 等分子比分母小的分数)
n1=(int)(Math.random()*99+1);
n2=(int)(Math.random()*99+1);
n1<n2则运算数为n1/n2,否则运算数为n1/n2,
利用循环生成第2,3.....个运算数。
乘号用 × 表示;除号用 ÷ 表示,代替 / 号。
任务2时乘号已用×表示,除号用÷表示,无修改。
算式中,运算符与运算数之间必须加空格,但若是分数形式,则不需要,如:3 + 1/2 。
在运算数生成时,每个运算数生成分数或自然数具有随机性。
算式中,运算符与运算数之间必须加空格,但若是分数形式,则不需要,如:3 + 1/2 。
由于都是双目运算符,直接在运算符左右加上了空格。
能随机生成 2~3 个运算符的算式,如:2 + 3 * 4 ,注意此算式的答案也必须按照运算优先级进行计算。
由于双目运算符,运算数个数为运算符个数+1。
循环控制生成的运算数的个数。
能生成带括号的算式,如 (2 + 3) * 4 和 3 / (4 + 2)。括号的运算优先级要高于加减乘除。
int bracketsNum=(int)(Math.random()*operatorNum);
随机数绝对出现括号的对数
将随机生成的运算式以空格分离出多个字符串保存在字符串数组中,随机数决定左右括号出现的位置。
如:左括号出现在第一个数则记为1,有括号出现在第二个数则记为2
String[] bracketLocation=new String[bracketsNum];
String数组用于记录括号的位置,为12;
在生成括号时进行检测避免如 ((1+2))的出现。
另外检测左右括号是否出现在同一位置的两边如:(1),出现则break从新生成。
对生成的运算式进行括号匹配,检测运算式的格式是否正确。
String[] strlist=str.split(" ");
int withBracketNum=0;
while (true) {
int flag=0;
for (int i=0;i<bracketsNum;i++) {
int leftBracketLocation=(int)(Math.random()*(operatorNum));
int rightBracketLocation=(int)(Math.random()*(operatorNum-leftBracketLocation)
+leftBracketLocation+1);
for (String s:bracketLocation) {
if(s==null)
break;
if (s.equals(leftBracketLocation+""+rightBracketLocation)) {
flag=1;
break;
}
}
if((leftBracketLocation+rightBracketLocation)==operatorNum || flag==1)
continue;
bracketLocation[withBracketNum]=leftBracketLocation+""+rightBracketLocation;
withBracketNum++;
strlist[leftBracketLocation*2] = "( " + strlist[leftBracketLocation*2];
strlist[rightBracketLocation*2] = strlist[rightBracketLocation*2] + " )";
}
String temp="";
for (int i=0;i<strlist.length;i++) {
temp += strlist[i];
}
if(bracketCheck(temp)) {
break;
}
}
在用户输入答案后,除显示对错之外,还需要显示此题的正确答案。
主要问题在于对运算式的求值,参考了提供的调度场算法,以及搜素得到的逆波兰式求值。
将计算分为2步进行:
- 转换为后缀表达式
创建一个符号栈。
遍历中缀表达式,若是数字则输出成为后缀表达式的一部分。
若是符号,判断与栈顶符号的优先级,若低于或等于栈顶符号优先级,栈顶符号出栈,否则入栈。
( 优先级最高,乘除 优先级高于 加减。
到符号为 ) 时,栈顶元素依次出栈并输出直到栈顶元素为 ( 时停止,将 ( 出栈不输出。
public String calPoland(String str) {
String goal="";
Stack<String> character=new Stack<String>();
String[] c=str.split(" ");
for(int i=0;i<c.length;i++)
{
switch(c[i])
{
case "+":
case "-":
while(!character.empty()) {
if(character.peek().equals("("))
break;
goal += character.pop()+" ";
}
character.push(c[i]);
break;
case "×":
case "÷":
while(!character.empty()) {
if(character.peek().equals("("))
break;
if (character.peek().equals("×")||character.peek().equals("÷"))
{
goal +=character.pop()+" ";
}
else
break;
}
character.push(c[i]);
break;
case "(":
character.push("(");
break;
case ")":
while (true)
{
if (character.peek().equals("(")) {
character.pop();
break;
}
else
goal += character.pop()+" ";
}
break;
default:
goal+=c[i]+" ";
break;
}
}
while(!character.empty()){
goal+=character.pop()+" ";
}
return goal;
}
- 利用后缀表达式进行计算
创建一个数字栈。
遍历后缀表达式,
若是数字则入栈。
若是运算符,从数栈中取出2个运算数(若不足2个则后缀表达式错误),
进行运算并将结果压入数栈。(先取出的为运算数2,后取出的为运算数1)
public String calculate(String str) {
...
switch (strlist[i])
{
case "+":
for(int j=0;j<2;j++) {
if (c.peek().indexOf("/") >= 0) {
String[] s = c.pop().split("/");
n[2*j] = Integer.parseInt(s[0]);
n[2*j + 1] = Integer.parseInt(s[1]);
} else {
n[2*j] = Integer.parseInt(c.pop());
n[2*j + 1] = 1;
}
}
c.push(add(n[2],n[3],n[0],n[1]));
break;
case "-":
for(int j=0;j<2;j++) {
if (c.peek().indexOf("/") >= 0) {
String[] s = c.pop().split("/");
n[2*j] = Integer.parseInt(s[0]);
n[2*j + 1] = Integer.parseInt(s[1]);
} else {
n[2*j] = Integer.parseInt(c.pop());
n[2*j + 1] = 1;
}
}
c.push(reduce(n[2],n[3],n[0],n[1]));
break;
case "×":
for(int j=0;j<2;j++) {
if (c.peek().indexOf("/") >= 0) {
String[] s = c.pop().split("/");
n[2*j] = Integer.parseInt(s[0]);
n[2*j + 1] = Integer.parseInt(s[1]);
} else {
n[2*j] = Integer.parseInt(c.pop());
n[2*j + 1] = 1;
}
}
c.push(multipy(n[2],n[3],n[0],n[1]));
break;
case "÷":
for(int j=0;j<2;j++) {
if (c.peek().indexOf("/") >= 0) {
String[] s = c.pop().split("/");
n[2*j] = Integer.parseInt(s[0]);
n[2*j + 1] = Integer.parseInt(s[1]);
} else {
n[2*j] = Integer.parseInt(c.pop());
n[2*j + 1] = 1;
}
}
c.push(divide(n[2],n[3],n[0],n[1]));
break;
default:
c.push(strlist[i]);
break;
}
...
}