Java实现简单计算器(新手向)

用Java实现简单计算器(新手向)

需求:用java实现简易计算器,包含加减乘除和括号功能。

分析:这是一道较常规的java试题,算术运算按顺序倒是好办,但是加上括号就不一样了,比如:5*(4+3),就得先算括号里面的(4+3)再进行括号外的乘法运算。
我们这里可以使用两个栈:一个存放数字,一个存放符号,以及一个运算符优先级表。

先弄两个栈

	public static final Stack<Integer> DIGITALSTACK = new Stack<>(); // 数字栈
	public static final Stack<Character> SYMBLESTACK = new Stack<>(); // 运算符栈

一个栈存放数字,一个存放运算符。

然后弄一个二维表存放运算符优先级顺序

我们就可以将栈顶运算符和当前遍历到的运算符对照这个表进行比较。
ps:‘#’是我们自己加进去的(当然用其他符号也可(~ ̄▽ ̄)~),我们要先把‘#’,压入符号栈中,作用是可以与第一个运算符进行比较。

	/*
	 * 运算符优先级表
	 * 0 : 栈顶运算符弹出
	 * 1 : 当前运算符入栈
	 * -1 : 操作数和运算符弹出进行运算后入栈
	 */
	public static final int[][] TABLE= { 
		/*    #  +  -  *  /  (  )      当前运算符  */
	/* # */	{ 0, 1, 1, 1, 1, 1, 0 },
	/* + */	{-1,-1,-1, 1, 1, 1,-1 },
	/* - */	{-1,-1,-1, 1, 1, 1,-1 },
	/* * */	{-1,-1,-1,-1,-1, 1,-1 },
	/* / */	{-1,-1,-1,-1,-1, 1,-1 },
	/* ( */	{ 0, 1, 1, 1, 1, 1, 0 },
	/* ) */	{ 0, 0, 0, 0, 0, 0, 0 },
	/*  栈顶运算符  */
	};

这里0表示:将栈顶运算符弹出
1:将当前运算符入栈
-1:将数字栈的两个数字出栈,符号栈的栈顶运算符出栈,运算得出结果后push进数字栈。

正式开工

	public int calculate(String str) {
		str += '#';
		SYMBLESTACK.push('#');
		int length =  str.length();
		boolean flag = false; // 判断是否为连续数字 (上一个是否为数字)
		for(int i = 0; i < length; i++) {
			char c = str.charAt(i);
			if(Character.isDigit(c)) { // 当前字符为数字
				if(flag) { // 上一字符为数字
					int t = DIGITALSTACK.pop();
					t = t * 10 + c - '0';
					DIGITALSTACK.push(t);
				}else {
					DIGITALSTACK.push(c - '0');
					flag = true;
				}
			}else { // 当前字符为符号
				char pre = SYMBLESTACK.peek();
				char now = c;
				switch(TABLE[changeDig(pre)][changeDig(now)]) {
				case 0 : SYMBLESTACK.pop(); break;
				case 1 : SYMBLESTACK.push(c); break;
				case -1 :
					i--; // 退一位
					int num = yunSuan(DIGITALSTACK.pop(),DIGITALSTACK.pop(),SYMBLESTACK.pop());
					DIGITALSTACK.push(num);
					break;
				default : break;
				}
				flag = false;
			}
		}
		
		return DIGITALSTACK.pop();
	}

我们先把原传入的字符串后面加个‘#’,目的是可以与开始push进操作符栈的‘#’进行比较并弹出。
由于我们是按照字符串一个一个字符去遍历的,当我们遇到连续数字时,例如12,我们的做法是先把1入栈,然后遍历到2的时候,判断上一字符串是否为数字,若是,则把1弹出,乘10,加2,再把得到的12入栈,就ok啦( ̄▽ ̄)。

再贴上工具类

	/*
	 * 将字符转换为二维表的下标
	 */
	private int changeDig(char c) {
		int dig = 0;
		switch(c) {
		case '#' : dig = 0; break;
		case '+' : dig = 1; break;
		case '-' : dig = 2; break;
		case '*' : dig = 3; break;
		case '/' : dig = 4; break;
		case '(' : dig = 5; break;
		case ')' : dig = 6; break;
		default : break;
		}
		return dig;
	}
	/*
	 * 运算
	 * 注意出入栈顺序
	 */
	private int yunSuan(int numOne, int numTwo, char c) {
		int result = 0;
		switch(c) {
		case '+' : result = numTwo + numOne; break;
		case '-' : result = numTwo - numOne; break;
		case '*' : result = numTwo * numOne; break;
		case '/' : result = numTwo / numOne; break;
		}
		return result;
	}

至此,就算基本完成啦( •̀ ω •́ )✧

完整代码贴贴

public class Calculate {
	/*
	 * 运算符优先级表
	 * 0 : 栈顶运算符弹出
	 * 1 : 当前运算符入栈
	 * -1 : 操作数和运算符弹出进行运算后入栈
	 */
	public static final int[][] TABLE= { 
		/*    #  +  -  *  /  (  )      当前运算符  */
	/* # */	{ 0, 1, 1, 1, 1, 1, 0 },
	/* + */	{-1,-1,-1, 1, 1, 1,-1 },
	/* - */	{-1,-1,-1, 1, 1, 1,-1 },
	/* * */	{-1,-1,-1,-1,-1, 1,-1 },
	/* / */	{-1,-1,-1,-1,-1, 1,-1 },
	/* ( */	{ 0, 1, 1, 1, 1, 1, 0 },
	/* ) */	{ 0, 0, 0, 0, 0, 0, 0 },
	/*  栈顶运算符  */
	};
	public static final Stack<Integer> DIGITALSTACK = new Stack<>(); // 数字栈
	public static final Stack<Character> SYMBLESTACK = new Stack<>(); // 运算符栈
	
	public int calculate(String str) {
		str += '#';
		SYMBLESTACK.push('#');
		int length =  str.length();
		boolean flag = false; // 判断是否为连续数字 (上一个是否为数字)
		for(int i = 0; i < length; i++) {
			char c = str.charAt(i);
			if(Character.isDigit(c)) { // 当前字符为数字
				if(flag) { // 上一字符为数字
					int t = DIGITALSTACK.pop();
					t = t * 10 + c - '0';
					DIGITALSTACK.push(t);
				}else {
					DIGITALSTACK.push(c - '0');
					flag = true;
				}
			}else { // 当前字符为符号
				char pre = SYMBLESTACK.peek();
				char now = c;
				switch(TABLE[changeDig(pre)][changeDig(now)]) {
				case 0 : SYMBLESTACK.pop(); break;
				case 1 : SYMBLESTACK.push(c); break;
				case -1 :
					i--; // 退一位
					int num = yunSuan(DIGITALSTACK.pop(),DIGITALSTACK.pop(),SYMBLESTACK.pop());
					DIGITALSTACK.push(num);
					break;
				default : break;
				}
				flag = false;
			}
		}
		
		return DIGITALSTACK.pop();
	}
	
	/*
	 * 将字符转换为二维表的下标
	 */
	private int changeDig(char c) {
		int dig = 0;
		switch(c) {
		case '#' : dig = 0; break;
		case '+' : dig = 1; break;
		case '-' : dig = 2; break;
		case '*' : dig = 3; break;
		case '/' : dig = 4; break;
		case '(' : dig = 5; break;
		case ')' : dig = 6; break;
		default : break;
		}
		return dig;
	}
	/*
	 * 运算
	 * 注意出入栈顺序
	 */
	private int yunSuan(int numOne, int numTwo, char c) {
		int result = 0;
		switch(c) {
		case '+' : result = numTwo + numOne; break;
		case '-' : result = numTwo - numOne; break;
		case '*' : result = numTwo * numOne; break;
		case '/' : result = numTwo / numOne; break;
		}
		return result;
	}
	
}

骚微测试下

public class MyTest {
	public static void main(String[] args) {
		Calculate cal = new Calculate();
		String str = "12*(8-4)+36";
		System.out.println(str+"的运算结果是:");
		System.out.println(cal.calculate(str));
	}

}

运算正确
完工。
其实应该判断字符串是否为正确运算式的,偷懒(●’◡’●)

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值