1、核心:
(1)計算器的每一次輸入要檢查合法性
(2)計算的核心是把從文本編輯框獲得的內容進行分離,將數字壓入數字棧,符號進行優先級判斷後壓入符號棧,然後依次取出運算得到結果。
(3)計算流程圖(由於電腦之前重裝了,沒有億圖,流程圖不多就用寫的了)
(4)重要代碼
1、這個函數是對輸入的運算式進行檢查,如果輸入的有錯誤,就進行提示,並且將輸入框鎖定。
(代碼註釋比較多,這裏就不多說了)
private void TipChecker(String tipcommand1,String tipcommand2){
//Tipcode1表示數據類型,Tipcode2表示名詞類型解釋
int Tipcode1=0,Tipcode2=0;
//表示命令類型
int tiptype1=0,tiptype2=0;
//括號數
int bracket=0;
//+-*/^)根號 不能作爲第一位
if(tipcommand1.compareTo("#")==0&&(tipcommand2.compareTo("÷")==0||tipcommand2.compareTo("")==0||tipcommand2.compareTo("+")==0||tipcommand2.compareTo(")")==0||tipcommand2.compareTo("")==0||tipcommand2.compareTo("^")==0)){Tipcode1=-1;}
//定義存儲字符串中最後一位的類型
elseif(tipcommand1.compareTo("#")!=0){if(tipcommand1.compareTo("(")==0){tiptype1=1;}elseif(tipcommand1.compareTo(")")==0){tiptype1=2;}else if(tipcommand1.compareTo(".")==0){tiptype1=3;}else if("0123456789".indexOf(tipcommand1)!=-1){tiptype1=4;}
else if("+-×÷".indexOf(tipcommand1)!=-1){tiptype1=5;}else if("√^".indexOf(tipcommand1)!=-1){tiptype1=6;}else if("sincostanlnlogn!".indexOf(tipcommand1)!=-1){tiptype1=7;}
//定義欲輸入的按鍵類型
if(tipcommand2.compareTo("(")==0){tiptype2=1;}else if(tipcommand2.compareTo(")")==0){tiptype2=2;}else if(tipcommand2.compareTo(".")==0){tiptype2=3;}else if("0123456789".indexOf(tipcommand1)!=-1){tiptype2=4;}
else if("+-×÷".indexOf(tipcommand2)!=-1){tiptype2=5;}else if("√^".indexOf(tipcommand2)!=-1){tiptype2=6;}else if("sincostanlnlogn!".indexOf(tipcommand2)!=-1){tiptype2=7;}
switch(tiptype1){
case 1://左括號後面直接接右括號,“+*/”(符號不算),或者“根號^”
if(tiptype2==2||(tiptype2==5&&tipcommand2.compareTo("-")!=0)||tiptype2==6) Tipcode1=1; break;
case 2://右括號後面接左括號、數字、“+-*/sin^...”
if(tiptype2==1||tiptype2==3||tiptype2==4||tiptype2==7) Tipcode1=2; break;
case 3://"."後面接左括號或者sincon...
if(tiptype2==1||tiptype2==7) Tipcode1=3;
//連續輸入兩個“.”
if(tiptype2==3) Tipcode1=8; break;
case 4://數字後面直接接左括號或者“sincon...”
if(tiptype2==1||tiptype2==7) Tipcode1=4;break;
case 5://+-×÷後面直接接右括號,+-×÷根號^
if(tiptype2==2||tiptype2==5||tiptype2==6) Tipcode1=5;break;
case 6://根號^後面直接接右括號,+-×÷根號^以及“sincos...”
if(tiptype2==2||tiptype2==5||tiptype2==6||tiptype2==7) Tipcode1=6;break;
case 7://sincos...後面直接接右括號“+-*/根號^”以及sincos
if(tiptype2==2||tiptype2==5||tiptype2==6||tiptype2==7) Tipcode1=7;break;
}
}//(tipcommand1.compareTo("#")!=0)
//檢測小數點的重複性,Tipcondel=0,表明滿足前面的規則
if(Tipcode1==0 &&tipcommand2.compareTo(".")==0){
int tip_point=0;
for(int i=0;i<tip_i;i++){
if(Tipcommand[i].compareTo(".")==0)
tip_point++;
//若出現以下幾個運算符之一,小數點計數清零
if(Tipcommand[i].compareTo("sin")==0||Tipcommand[i].compareTo("cos")==0||Tipcommand[i].compareTo("tan")==0||
Tipcommand[i].compareTo("log")==0||Tipcommand[i].compareTo("ln")==0||Tipcommand[i].compareTo("n!")==0
||Tipcommand[i].compareTo("√")==0||Tipcommand[i].compareTo("^")==0||Tipcommand[i].compareTo("+")==0
||Tipcommand[i].compareTo("-")==0||Tipcommand[i].compareTo("×")==0||Tipcommand[i].compareTo("÷")==0
||Tipcommand[i].compareTo("(")==0||Tipcommand[i].compareTo(")")==0){tip_point=0;}
}
tip_point++;
//若小數點計數大於1,表明小數點重複了
if(tip_point>1){Tipcode1 = 8;}
}//if(Tipcode1==0 &&tipcommand2.compareTo(".")==0){}
//檢測右括號是否匹配
if(Tipcode1==0 &&tipcommand2.compareTo(")")==0){
int tip_right_bracket=0;
for(int i=0;i<tip_i;i++){if(Tipcommand[i].compareTo("(")==0)tip_right_bracket++;if(Tipcommand[i].compareTo(")")==0)tip_right_bracket--;}
if(tip_right_bracket==0){Tipcode1=10;}
}
//檢測輸入=的合法性
if(Tipcode1==0 &&tipcommand2.compareTo("=")==0){
int tip_bracket=0;
for(int i=0;i<tip_i;i++){if(Tipcommand[i].compareTo("(")==0){tip_bracket++;}if(Tipcommand[i].compareTo(")")==0){tip_bracket--;}}
//若大於0,表明左括號還有未比配的
if(tip_bracket>0){Tipcode1=9;bracket=tip_bracket;}
//若前一個字符是以下之一,表明=不合法
else if(tip_bracket==0){if("√^sincostanlnlogn!".indexOf(tipcommand1)!=-1){Tipcode1=6;}
if("+-×÷".indexOf(tipcommand1)!=-1){Tipcode1=5;}}
}
//顯示幫助和錯誤信息
TipShow(bracket,Tipcode1,Tipcode2,tipcommand1,tipcommand2);
}//private void TipChecker(String tipcommand1,String tipcommand2){}
2、計算部分的代碼
public void process(String str) {
int weightPlus = 0, topOp = 0,
topNum = 0, flag = 1, weightTemp = 0;
//weightPlus爲同一()下的基本優先級,weightTemp臨時記錄優先級的變化
//topOp爲weight[],operator[]的計數器;topNum爲number[]的計數器
//flag爲正負數的計數器,1爲正數,-1爲負數
int weight[]; //保存operator棧中運算符的優先級,以topOp計數
double number[]; //保存數字,以topNum計數
char ch, ch_gai, operator[];//operator[]保存運算符,以topOp計數
String num;//記錄數字,str以+-×÷()sctgl!√^分段,+-×÷()sctgl!√^字符之間的字符串即爲數字
weight = new int[MAXLEN];
number = new double[MAXLEN];
operator = new char[MAXLEN];
String expression = str;
StringTokenizer expToken = new StringTokenizer(expression,"+-×÷()sctgl!√^");
int i = 0;
while (i < expression.length()) {
ch = expression.charAt(i);
//判斷正負數
if (i == 0) {
if (ch == '-')
flag = -1;
} else if(expression.charAt(i-1) == '(' && ch == '-')
flag = -1;
//取得數字,並將正負符號轉移給數字
if (ch <= '9' && ch >= '0'|| ch == '.' || ch == 'E') {
num = expToken.nextToken();
ch_gai = ch;
Log.e("guojs",ch+"--->"+i);
//取得整個數字
while (i < expression.length() &&
(ch_gai <= '9' && ch_gai >= '0'|| ch_gai == '.' || ch_gai == 'E'))
{
ch_gai = expression.charAt(i++);
Log.e("guojs","i的值爲:"+i);
}
//將指針退回之前的位置
if (i >= expression.length()) i-=1; else {i-=2;}
if (num.compareTo(".") == 0) number[topNum++] = 0;
//將正負符號轉移給數字
else {
number[topNum++] = Double.parseDouble(num)*flag;
flag = 1;
}
}
//計算運算符的優先級
if (ch == '(') weightPlus+=4;
if (ch == ')') weightPlus-=4;
if (ch == '-' && flag == 1 || ch == '+' || ch == '×'|| ch == '÷' ||
ch == 's' ||ch == 'c' || ch == 't' || ch == 'g' || ch == 'l' ||
ch == '!' || ch == '√' || ch == '^') {
switch (ch) {
//+-的優先級最低,爲1
case '+':
case '-':
weightTemp = 1 + weightPlus;
break;
//x÷的優先級稍高,爲2
case '×':
case '÷':
weightTemp = 2 + weightPlus;
break;
//sincos之類優先級爲3
case 's':
case 'c':
case 't':
case 'g':
case 'l':
case '!':
weightTemp = 3 + weightPlus;
break;
//其餘優先級爲4
//case '^':
//case '√':
default:
weightTemp = 4 + weightPlus;
break;
}
//如果當前優先級大於堆棧頂部元素,則直接入棧
if (topOp == 0 || weight[topOp-1] < weightTemp) {
weight[topOp] = weightTemp;
operator[topOp] = ch;
topOp++;
//否則將堆棧中運算符逐個取出,直到當前堆棧頂部運算符的優先級小於當前運算符
}else {
while (topOp > 0 && weight[topOp-1] >= weightTemp) {
switch (operator[topOp-1]) {
//取出數字數組的相應元素進行運算
case '+':
number[topNum-2]+=number[topNum-1];
break;
case '-':
number[topNum-2]-=number[topNum-1];
break;
case '×':
number[topNum-2]*=number[topNum-1];
break;
//判斷除數爲0的情況
case '÷':
if (number[topNum-1] == 0) {
showError(1,str_old);
return;
}
number[topNum-2]/=number[topNum-1];
break;
case '√':
if(number[topNum-1] == 0 || (number[topNum-2] < 0 &&
number[topNum-1] % 2 == 0)) {
showError(2,str_old);
return;
}
number[topNum-2] =
Math.pow(number[topNum-2], 1/number[topNum-1]);
break;
case '^':
number[topNum-2] =
Math.pow(number[topNum-2], number[topNum-1]);
break;
//計算時進行角度弧度的判斷及轉換
//sin
case 's':
if(drg_flag == true) {
number[topNum-1] = Math.sin((number[topNum-1]/180)*pi);
} else {
number[topNum-1] = Math.sin(number[topNum-1]);
}
topNum++;
break;
//cos
case 'c':
if(drg_flag == true) {
number[topNum-1] = Math.cos((number[topNum-1]/180)*pi);
} else {
number[topNum-1] = Math.cos(number[topNum-1]);
}
topNum++;
break;
//tan
case 't':
if(drg_flag == true) {
if((Math.abs(number[topNum-1])/90)%2 == 1) {
showError(2,str_old);
return;
}
number[topNum-1] = Math.tan((number[topNum-1]/180)*pi);
} else {
if((Math.abs(number[topNum-1])/(pi/2))%2 == 1) {
showError(2,str_old);
return;
}
number[topNum-1] = Math.tan(number[topNum-1]);
}
topNum++;
break;
//log
case 'g':
if(number[topNum-1] <= 0) {
showError(2,str_old);
return;
}
number[topNum-1] = Math.log10(number[topNum-1]);
topNum++;
break;
//ln
case 'l':
if(number[topNum-1] <= 0) {
showError(2,str_old);
return;
}
number[topNum-1] = Math.log(number[topNum-1]);
topNum++;
break;
//階乘
case '!':
if(number[topNum-1] > 170) {
showError(3,str_old);
return;
} else if(number[topNum-1] < 0) {
showError(2,str_old);
return;
}
number[topNum-1] = N(number[topNum-1]);
topNum++;
break;
}
//繼續取堆棧的下一個元素進行判斷
topNum--;
topOp--;
}
//將運算符如堆棧
weight[topOp] = weightTemp;
operator[topOp] = ch;
topOp++;
}
}
i++;
}
//依次取出堆棧的運算符進行運算
while (topOp>0) {
//+-x直接將數組的後兩位數取出運算
switch (operator[topOp-1]) {
case '+':
number[topNum-2]+=number[topNum-1];
break;
case '-':
number[topNum-2]-=number[topNum-1];
break;
case '×':
number[topNum-2]*=number[topNum-1];
break;
//涉及到除法時要考慮除數不能爲零的情況
case '÷':
if (number[topNum-1] == 0) {
showError(1,str_old);
return;
}
number[topNum-2]/=number[topNum-1];
break;
case '√':
if(number[topNum-1] == 0 || (number[topNum-2] < 0 &&
number[topNum-1] % 2 == 0)) {
showError(2,str_old);
return;
}
number[topNum-2] =
Math.pow(number[topNum-2], 1/number[topNum-1]);
break;
case '^':
number[topNum-2] =
Math.pow(number[topNum-2], number[topNum-1]);
break;
//sin
case 's':
if(drg_flag == true) {
number[topNum-1] = Math.sin((number[topNum-1]/180)*pi);
} else {
number[topNum-1] = Math.sin(number[topNum-1]);
}
topNum++;
break;
//cos
case 'c':
if(drg_flag == true) {
number[topNum-1] = Math.cos((number[topNum-1]/180)*pi);
} else {
number[topNum-1] = Math.cos(number[topNum-1]);
}
topNum++;
break;
//tan
case 't':
if(drg_flag == true) {
if((Math.abs(number[topNum-1])/90)%2 == 1) {
showError(2,str_old);
return;
}
number[topNum-1] = Math.tan((number[topNum-1]/180)*pi);
} else {
if((Math.abs(number[topNum-1])/(pi/2))%2 == 1) {
showError(2,str_old);
return;
}
number[topNum-1] = Math.tan(number[topNum-1]);
}
topNum++;
break;
//對數log
case 'g':
if(number[topNum-1] <= 0) {
showError(2,str_old);
return;
}
number[topNum-1] = Math.log10(number[topNum-1]);
topNum++;
break;
//自然對數ln
case 'l':
if(number[topNum-1] <= 0) {
showError(2,str_old);
return;
}
number[topNum-1] = Math.log(number[topNum-1]);
topNum++;
break;
//階乘
case '!':
if(number[topNum-1] > 170) {
showError(3,str_old);
return;
} else if(number[topNum-1] < 0) {
showError(2,str_old);
return;
}
number[topNum-1] = N(number[topNum-1]);
topNum++;
break;
}
//取堆棧下一個元素計算
topNum--;
topOp--;
}
//如果是數字太大,提示錯誤信息
if(number[0] > 7.3E306) {
showError(3,str_old);
return;
}
//輸出最終結果
input.setText(String.valueOf(FP(number[0])));
tip.setText("計算完畢,要繼續請按歸零鍵 C");
mem.setText(str_old+"="+String.valueOf(FP(number[0])));
}
2.下週計劃:藍牙