java高级计算器的实现

不仅可以实现+,-,*,/,( ,) ,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;
					//×÷的优先级为2
				case '÷':
				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;
							//ln
						case 'l':
							if(number[topNum-1]<=0){
								System.out.println("对数ln值有误");
								return;
							}
							number[topNum-1] = Math.log(number[topNum-1]);
							topNum++;
							break;
							//log
						case '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;
				//ln
			case 'l':
				if(number[topNum-1]<=0){
					System.out.println("对数ln值有误");
					return;
				}
				number[topNum-1] = Math.log(number[topNum-1]);
				topNum++;
				break;
				//log
			case '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>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值