java高级计算器的实现

来源:互联网 发布:伏尔加河上的纤夫知乎 编辑:程序博客网 时间:2024/05/19 13:43
不仅可以实现+,-,*,/,( ,) ,log ,ln,√ , ^ , cos ,sin,tan ,还支持最大500长度的字符运算。本程序是我上课的时候老师讲的,可能不是老师的原创,希望对有些同学有用,不扯了,上图:
import java.text.DecimalFormat;import java.util.StringTokenizer;/** * 计算器的核心内容: * 1.计算部分:必须建立在无错误的结论下 *2.数据格式化 *3.阶乘算法 *4.错误提示 * @author asus * */public class Calc {//设定最大的运算符长度private static final int MAXLEN = 500 ;/** * 计算表达式的字符串形式 * 从左到右扫面,数字先入number栈,运算符入operator栈 * +-基本优先级为1 *÷的优先级为2,log ln sin cos tan n!的优先级为3,开方,乘方的优先级为4 * 括号内存运算法的优先级高于4 * 当前运算符优先级高于栈顶压栈,低于栈顶弹出一个运算符与两个数字进行运算 * 重复直到运算符大于栈顶 * 扫面完之后对剩下的运算符与数字依次进行计算 * @param str */public static void process(String str , boolean drag_flag){int weightPlus = 0 ;  //记录同一个()的基本优先级int topTop = 0 ; //数组计数器int topNum = 0 ;int flag  =1 ;   //判断正负 1为正数 -1为负数int weightTemp = 0 ; //记录临时优先级的变化int weight[]  = new int[MAXLEN];double[] number = new double[MAXLEN] ;char ch , ch_gai , operator[] = new char[MAXLEN] ;String num ; // 记录数字 str将以+-×÷()sctgl!√ ^分割,字符串之间即为数字String experssion = str ;StringTokenizer expToken = new StringTokenizer(experssion, "+-×÷()sctgl!√ ^");int i =0  ;while(i<experssion.length()){ch = experssion.charAt(i);//判断正负数if(i==0){if(ch == '-'){flag = -1 ;}}else if(experssion.charAt(i-1)=='(' && ch == '-')flag = -1 ;//取得数字,将正负号交给该数字if(ch>='0' &&  ch<='9' || ch=='.'|| ch=='E'){num = expToken.nextToken();ch_gai = ch ;while(i<experssion.length() && (ch_gai>= '0' && ch_gai <= '9' || ch_gai == '.' || ch_gai == 'E')){ch_gai = experssion.charAt(i++);System.out.println("i的值为:"+i+" , ch_gai的值为:"+ch_gai);}if(i >= experssion.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 == '÷' || ch == 's' || ch == 'c' || ch == 't' || ch == 'l' || ch == 'g' || ch == '!' || ch == '√' || ch == '^'){switch(ch){//+-的优先级最低case '+':case '-':weightTemp = weightPlus + 1 ;break;//×÷的优先级为2case '÷':case '×':weightTemp = weightPlus + 2 ;break;case 's':case 'c':case 't':case 'l':case 'g':case '!':weightTemp = weightPlus + 3 ;break;case '√':case '^':default:weightTemp = weightPlus + 4 ;break;}//如果当前优先级大于栈顶的元素,则直接入栈if(topTop == 0 || weight[topTop -1] < weightTemp){weight[topTop] = weightTemp;operator[topTop] = ch ;System.out.println("============"+ch+"========");topTop++ ;}else{ //否则将堆栈中的运算符逐个取出,直到当前栈顶部运算符的优先级小于当前运算符while(topTop>0 && weight[topTop-1] > weightTemp){switch(operator[topTop-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){System.out.println("0不能为除数");return ;}number[topNum-2] /= number[topNum-1];break;case '√'://负值不能开偶次方if(number[topNum-1] == 0 || (number[topNum-2] < 0 && number[topNum-1] % 2 == 0)){System.out.println("平方数不存在或者负数不能开偶次行!");return ;}number[topNum-2] = Math.pow(number[topNum-1], 1/number[topNum-2]);break;case '^':number[topNum-2] = Math.pow(number[topNum-2], number[topNum-1]);break;case 's'://角度if(drag_flag){number[topNum-1] = Math.sin(number[topNum-1]*Math.PI/180);}else{//此时为弧度number[topNum-1] = Math.sin(number[topNum-1]);}topNum ++ ;break;case 'c':if(drag_flag){number[topNum-1] = Math.cos(number[topNum-1]*Math.PI/180);}else{number[topNum-1] = Math.cos(number[topNum-1]);}topNum++;break;case 't':if(drag_flag){if(Math.abs(number[topNum-1]%90) == 1){System.out.println("tan取值有错误");return;}number[topNum-1] = Math.tan(number[topNum-1]*Math.PI/180);}else{if(Math.abs(number[topNum-1] % Math.PI * 2) ==1){System.out.println("tan取值有错误");return;}number[topNum-1] = Math.tan(number[topNum-1]);}topNum++;break;//lncase 'l':if(number[topNum-1]<=0){System.out.println("对数ln值有误");return;}number[topNum-1] = Math.log(number[topNum-1]);topNum++;break;//logcase 'g':if(number[topNum-1]<=0){System.out.println("对数log值有误");return;}number[topNum-1] = Math.log10(number[topNum-1]);topNum++;break;case '!':if(number[topNum-1]<0){System.out.println("阶乘数有误");return ;}number[topNum-1] = getN(number[topNum-1]);topNum++;break;}//继续堆栈下一个元素判断topNum -- ;topTop -- ;}//将运算符压入栈中weight[topTop] = weightTemp ;operator[topTop] = ch ;topTop++ ; }}i++ ; }//依次取出堆运算中的运算符进行运算while(topTop>0){//直接将数组的后两位取出运算switch(operator[topTop-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){System.out.println("0不能为除数");return ;}number[topNum-2] /= number[topNum-1];break;case '√'://负值不能开偶次方if(number[topNum-1] == 0 || (number[topNum-2] < 0 && number[topNum-1] % 2 == 0)){System.out.println("平方数不存在或者负数不能开偶次方!");return ;}number[topNum-2] = Math.pow(number[topNum-1], 1/number[topNum-2]);break;case '^':number[topNum-2] = Math.pow(number[topNum-2], number[topNum-1]);break;case 's'://角度if(drag_flag){number[topNum-1] = Math.sin(number[topNum-1]*Math.PI/180);}else{//此时为弧度number[topNum-1] = Math.sin(number[topNum-1]);}topNum ++ ;break;case 'c':if(drag_flag){number[topNum-1] = Math.cos(number[topNum-1]*Math.PI/180);}else{number[topNum-1] = Math.cos(number[topNum-1]);}topNum++;break;case 't':if(drag_flag){if(Math.abs(number[topNum-1]%90) == 1){System.out.println("tan取值有错误");return;}number[topNum-1] = Math.tan(number[topNum-1]*Math.PI/180);}else{if(Math.abs(number[topNum-1] % Math.PI * 2) ==1){System.out.println("tan取值有错误");return;}number[topNum-1] = Math.tan(number[topNum-1]);}topNum++;break;//lncase 'l':if(number[topNum-1]<=0){System.out.println("对数ln值有误");return;}number[topNum-1] = Math.log(number[topNum-1]);topNum++;break;//logcase 'g':if(number[topNum-1]<0){System.out.println("对数log值有误");return;}number[topNum-1] = Math.log10(number[topNum-1]);topNum++;break;case '!':if(number[topNum-1]<0){System.out.println("阶乘数有误");return ;}number[topNum-1] = getN(number[topNum-1]);topNum++;break;}//取下一个元素计算topNum -- ;topTop -- ;}if(number[0]>7.3E306){System.out.println("计算数组过大");return ;}//数据显示:System.out.println("最终计算答案为:"+dataShow(number[0]));}private static  double getN(double n){if(n==0)return 1;double sum = 1.0;for(int s = 1 ; s <= n ; s++){sum *= s ;}return sum ;}private static String dataShow(double n){DecimalFormat format = new DecimalFormat("0.############");return format.format(n).toString();}public static void main(String[] args) {process("16+(7×l7)-90×g23+(1÷2)" ,true);}}
<span style="font-family: Arial, Helvetica, sans-serif;">由于比较懒,log就用g代替,ln就用l,sin用sin代替,cos用o代替,tan用t代替,不过这都不是重点,重点是这种处理的思想和方案.希望对大家有用,当然如果你喜欢,完全可以改一下做成一个android的应用,呵呵,我就做了一个,但是个人感觉本实验对android来说,并不是很优秀的算法,因为在每次输入的情况,都会对输入的字符串检测是否合法,显然对运算能力较弱的android来说有点吃力,不过,谁叫android也用java写呢????</span><span style="font-family: Arial, Helvetica, sans-serif;">呵呵</span>

0 0
原创粉丝点击