📄 calculate.java
字号:
/**
* @(#)Calculate.java
*
*
* @author ehtPossible高则宝 061251032
* @version 1.00 2007/5/29
*/
public class Calculate {
int hexDec = 10;//用来表示十进制或十六进制
int radAng = 1;//用来表示弧度制或角度制 0-弧度,1-角度
int[][] a = new int[50][2];
int[][] poland = new int[100][2];
int n=1;
int m=0;
public Calculate() {
}
public String DoCalculate(String s){
/*将字符串转化为二维数组,第一个整数记录该位是数字或者哪个符号(number-0, (-1, )-2, ^-3, ln-4, lg-5, sin-6, cos-7
*tan-8, cot-9, !-10, |-11, *-12, /-13, +-14, --15)
*如果该位是一个数,那么第二个整数记录着个数的具体数值
*另外为了之后转化逆波兰表达式方便,处理过程中会在转化出的数组的首尾一律添加一对括号*/
double[][] a = new double[50][2];
a[0][0]=1;
a[0][1]='(';//在表达式首添加一个括号'('
int n=1;//n可记录字符串s中数字及符号总个数
for (int i1 = 0; i1 < s.length(); ) {
//判断,若有小数点前或后不是数字,提示输入不合法
if(i1 >= 1 && s.charAt(i1) == '.' && (!isDigit(s.charAt(i1-1)) || !isDigit(s.charAt(i1-1)))){
return "Illegal Input";
}
if (isDigit(s.charAt(i1)) || s.charAt(i1) == '.') {
a[n][0]=0;
a[n][1]=0;
//读入十进制数字
if(hexDec == 10){
while (i1 < s.length() && isDigit(s.charAt(i1))) {
a[n][1] = a[n][1] * 10 + s.charAt(i1) - '0';
i1++;
}
if(i1 < s.length() && s.charAt(i1) == '.'){
i1++;
int index = 1;
while (i1 < s.length() && isDigit(s.charAt(i1))) {
a[n][1] = a[n][1] + (s.charAt(i1) - '0') * Math.pow(0.1, index);
i1++;
index++;
}
}
}
else{
//读入十六进制数字
while (i1 < s.length() && isDigit(s.charAt(i1))) {
if(s.charAt(i1) >= '0' && s.charAt(i1) <= '9')
a[n][1] = a[n][1] * 16 + s.charAt(i1) - '0';
else a[n][1] = a[n][1] * 16 + s.charAt(i1) - 'A' + 10;
i1++;
}
}
}
else if (s.charAt(i1)=='(') { a[n][0]=1; i1++; }
else if (s.charAt(i1)==')') { a[n][0]=2; i1++; }
else if (s.charAt(i1)=='^') { a[n][0]=3; i1++; }
else if (s.charAt(i1)=='|') { a[n][0]=11; i1++; }
else if (s.charAt(i1)=='*') { a[n][0]=12; i1++; }
else if (s.charAt(i1)=='/') { a[n][0]=13; i1++; }
//字符串中可能出现一元运算符,为了处理方便,在其前面加个0,改写成"0ln..." "0sin..."或者"0-..."
else if (s.charAt(i1)=='+' || s.charAt(i1)=='-'){
if(i1==0 || (s.charAt(i1-1)!=')'&& !Character.isDigit(s.charAt(i1-1)))){
a[n][0]=0;
a[n++][1]=0;
}
if(s.charAt(i1)=='+') { a[n][0]=14; i1 ++; }
else if(s.charAt(i1)=='-') { a[n][0]=15; i1 ++; }
}
else if (s.charAt(i1)=='l'|| s.charAt(i1)=='s'|| s.charAt(i1)=='c' || s.charAt(i1)=='t' ) {
a[n][0]=0;
a[n][1]=0;
n++;
if (s.charAt(i1)=='s') { a[n][0]=6; i1 += 3; }
else if(s.charAt(i1)=='t') { a[n][0]=8; i1 += 3; }
else if(s.charAt(i1)=='l'){
if(s.charAt(i1+1)=='n'){ a[n][0]=4; i1 += 2; }
else { a[n][0]=5; i1 += 2; }
}
else if(s.charAt(i1)=='c'){
if(s.charAt(i1+2)=='s'){ a[n][0]=7; i1 += 3; }
else { a[n][0]=9; i1 += 3; }
}
}
//阶乘运算符在数字之后,所以在!之后加0
else{
a[n][0] = 10;
i1++;
n++;
a[n][0] = 0;
a[n][1] = 0;
}
n++;
}
a[n][0]=2;
a[n][1]=')';//在表达式尾添加一个反括号
n++;//n加一后为字符串s中数字及符号总个数
//将数组转化为逆波兰表达式,a为输入的数组,n为其长度,poland存储输出的逆波兰表达式,m记录逆波兰表达式的长度
double[][] poland = new double[100][2];
int[] tempStack = new int[100];//转化所用的栈
int depth = 0;//栈的深度
int m=0;
for (int i = 0; i < n; i++) {
//如果该位是一个数或者是括号'(',,将其入栈
if (a[i][0]==0 || a[i][0]==1){
tempStack[depth]=i;
depth++;
}
//如果该位是反括号')',那么不断进行出栈操作直到有一个括号'('出栈
else if (a[i][0]==2) {
while (a[tempStack[depth-1]][0]!=1) {
depth--;
poland[m][0]=a[tempStack[depth]][0];
if(poland[m][0]==0)
poland[m][1]=a[tempStack[depth]][1];
m++;
}
depth--;
}
//如果该位是^,ln,lg,sin,cos,tan,cot,!,不断进行出栈操作直到栈顶元素是个括号(或+/-*|,然后将这个乘号或者除号入栈
else if (3 <= a[i][0] && a[i][0] <= 10) {
while (a[tempStack[depth-1]][0]==0 ||(3 <= a[tempStack[depth-1]][0] && a[tempStack[depth-1]][0] <= 10)) {
depth--;
poland[m][0]=a[tempStack[depth]][0];
if(poland[m][0]==0)
poland[m][1]=a[tempStack[depth]][1];
m++;
}
tempStack[depth]=i;
depth++;
}
//如果该位是模运算'|'乘号'*'或者除号'/',不断进行出栈操作直到栈顶元素是个括号'('或者加号'+'或者减号'-',然后将这个乘号或者除号入栈
else if (a[i][0]==11 || a[i][0]==12 || a[i][0]==13) {
while (a[tempStack[depth-1]][0] != 1 && a[tempStack[depth-1]][0] != 14 && a[tempStack[depth-1]][0] != 15) {
depth--;
poland[m][0]=a[tempStack[depth]][0];
if(poland[m][0]==0)
poland[m][1]=a[tempStack[depth]][1];
m++;
}
//tempStack[depth++]=i;
tempStack[depth] = i;
depth++;
}
//如果该位是加号'+'或者减号'-',不断进行出栈操作直到栈顶元素是个括号'(',然后将这个加号或者减号入栈
else if (a[i][0]==14 || a[i][0]==15) {
while (a[tempStack[depth-1]][0]!=1) {
depth--;
poland[m][0]=a[tempStack[depth]][0];
if(poland[m][0]==0)
poland[m][1]=a[tempStack[depth]][1];
m++;
}
tempStack[depth] = i;
depth++;
}
}
// 调试时用来检查依次读入的数字和运算符的数组以及转化后的逆波兰数组是否正确
System.out.println("n is "+ n);
for(int j = 0; j < n; j++){
System.out.print(a[j][0]+" "+a[j][1]+" ");
if( (j+2)%3==0) System.out.println();
}
System.out.println("\nm is "+m);
for(int k = 0; k < m; k++){
System.out.print(poland[k][0]+" "+poland[k][1]+" ");
if((k+2)%3==0) System.out.println();
}
//对逆波兰表达式求值,poland为逆波兰表达式,m为表达式长度
double[] resultArray = new double[100];//用来存放所求得的值
depth=0;//栈的深度
for (int i=0; i<m; i++) {
//如果是数字,放入用来运算及存储各步结果的resultArray中
if (poland[i][0]==0){
resultArray[depth]=poland[i][1];
depth++;
}
else{
double operand1,operand2;
operand2=resultArray[--depth];
operand1=resultArray[--depth];
//如果是非法表达式,必会在运算符前存入的不是数字,在此检验,并提示输入不合法
//if( depth -2 >= 0 && isDigit(String.valueOf(resultArray[depth-1])) && isDigit(String.valueOf(resultArray[depth-2]))){
//}
//else{
// return "Illegal Input";
//}
//定义各种运算符所表达的意义,其中阶乘!是对operand1运算,其它一元运算符仅对operand2运算
//若有不满足运算定义域的数值,也检验出并提示输入不合法
if (poland[i][0]==3){
if(( (operand1 == 0 && operand2 < 0)) || (operand1 < 0 && (1 / operand2) % 2 == 0 ) )
return "Illegal Input";
else resultArray[depth++]=Math.pow(operand1,operand2);
}
else if (poland[i][0]==4){
if(operand2 <= 0)
return "Illegal Input";
resultArray[depth++]=Math.log(operand2);
}
else if (poland[i][0]==5){
if(operand2 <= 0)
return "Illegal Input";
resultArray[depth++]=Math.log10(operand2);
}
else if (poland[i][0]==6){
if(radAng == 1){
resultArray[depth++]=Math.sin(operand2 / 180 * Math.PI);
}
else resultArray[depth++]=((int)(Math.sin(operand2) * 100000000)) / 100000000.0;
}
else if (poland[i][0]==7){
if(radAng == 1)
resultArray[depth++]=Math.sin(operand2 / 180 * Math.PI) / Math.tan(operand2 / 180 * Math.PI);
else
resultArray[depth++]=(int)(Math.sin(operand2) / Math.tan(operand2) * 100000000) / 100000000.0;
}
else if (poland[i][0]==8){
if(radAng == 1){
if( (operand2 + 90) % 180 == 0 )
return "Illegal Input";
else
resultArray[depth++]=Math.tan(operand2 / 180 * Math.PI);
}
else{
if( (operand2 + Math.PI / 2) % Math.PI == 0 )
return "Illegal Input";
else
resultArray[depth++]=Math.tan(operand2);}
}
else if (poland[i][0]==9){
if(radAng == 1){
if( operand2 % 180 == 0 )
return "Illegal Input";
else
resultArray[depth++]=1 / Math.tan(operand2 / 180 * Math.PI);
}
else{
if( operand2 % Math.PI == 0 )
return "Illegal Input";
else
resultArray[depth++]=1 / Math.tan(operand2);
}
}
else if (poland[i][0]==10){
if( operand1 < 0 || operand1 != (int)(operand1))
return "Illegal Input";
resultArray[depth++]=Factorial((int)(operand1));
}
else if (poland[i][0]==11){
if( operand2 == 0 )
return "Illegal Input";
resultArray[depth++]=operand1 % operand2;
}
else if (poland[i][0]==12) resultArray[depth++]= operand1 * operand2;
else if (poland[i][0]==13){
if( operand2 == 0 )
return "Illegal Input";
resultArray[depth++]=operand1 / operand2;
}
else if (poland[i][0]==14) resultArray[depth++]=operand1 + operand2;
else resultArray[depth++]=operand1 - operand2;
}
}
if(hexDec == 16)
return decToHex((int)(resultArray[0]));
else
return String.valueOf(resultArray[0]);
//return String.valueOf((int)(resultArray[0] * 1000000000.0) / 1000000000.0);
}
//判断某位上是否为数字
public boolean isDigit(String s){
boolean isDigit = true;
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) != '.' && !('0' <= s.charAt(i) && s.charAt(i) <= '9') )
isDigit = false;
}
return isDigit;
}
public boolean isDigit(char c){
if( ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') )
return true;
else
return false;
}
//用来计算阶乘的函数
public double Factorial(int n){
if(n == 0)
return 1;
else return n * Factorial(n -1);
}
//将十进制数字转化为十六进制字符串的函数
public static String decToHex(int value){
StringBuffer strBuf = new StringBuffer();
int[] a = new int[20];
int[] digit = new int[20];
int i=0,j=0;
a[0] = value / 16;
digit[0] = value % 16;
do{ i++;
digit[i] = a[i-1] % 16;
a[i] = a[i-1] / 16;
}while(a[i] != 0);
for(j = 0 ; j <= i ; j++){
char temp = ' ';
switch(digit[j]){
case 0 : temp = '0'; break; case 1 : temp = '1'; break;
case 2 : temp = '2'; break; case 3 : temp = '3'; break;
case 4 : temp = '4'; break; case 5 : temp = '5'; break;
case 6 : temp = '6'; break; case 7 : temp = '7'; break;
case 8 : temp = '8'; break; case 9 : temp = '9'; break;
case 10 : temp = 'A'; break; case 11 : temp = 'B'; break;
case 12 : temp = 'C'; break; case 13 : temp = 'D'; break;
case 14 : temp = 'E'; break; case 15 : temp = 'F'; break;
}
strBuf.append(temp);
}
strBuf.reverse();
return strBuf.toString();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -