我在网上看了很多的计算器都是那种没有实现优先级预算的,都是按照输入顺序来计算的,我不是很喜欢那种,然后我在网上查了查有没有别的办法,然后我知道逆波兰表达式,要实现优先级计算器,这个技能是要掌握的,有小伙伴感兴趣的话可以去网上查一查学一下,我在这就不多说,就简单的提一下
1.我么首先要考虑的是怎么获得逆波兰表达式
这时我们要定义两个栈,一个用来存放数字,一个存放符号,那么我么就要对原来的基础的表达式进行拆分,肯定会有人想到调用一个现成方法然后直接拆分成字符,这样操作不是很好 例如: 12+13 会被拆分成 1,2,+,1,3 ,所以要换一种方法
2.其次就是要考虑符号的优先级
/*
将数字和符号分离开我的思路是,给符号两边加上一个任意的字符,然后变成一个新的字符串,然后通过刚才加的这个字符来截取,来把他们分开
*/
function nbl(text){
var operand = []; //用于存放操作数的栈
var operator = []; //用于存放操作符的栈
var textArr = text.split('');
var newTextArr = [];
for(var i = 0; i < textArr.length; i++){
if(text[i] == "+"||text[i]== "-"||text[i]== "*"||text[i]== "/"||text[i]== "("||text[i]== ")" && text[i] != ".") //这里可以优化一下,我这样写就是直观容易理解一点{
newTextArr.push("|",text[i],"|");
}
else{
newTextArr.push(textArr[i]);
}
}
var calTextArr = newTextArr.join('').split("|");
calTextArr.unshift("#")
for(var i = 0; i < calTextArr.length; i++){
//如果是数字则直接入栈
if(Number(calTextArr[i]) || Number(calTextArr[i]) == 0){
operand.push(calTextArr[i]);
}
//如果是操作符则再根据不同的情况进行操作
else {
switch(true){
//如果operator栈顶是“(”或者遍历到的操作符是“(”则直接入栈
case calTextArr[i] == "(" && operator.slice(-1)[0] == "(":
operator.push(calTextArr[i]);
break;
/*如果遍历到的操作符是“)”则把operator中的操作符依次弹出并压入
operand中直至operator栈顶操作符为“(”,然后将“(”也弹出,但不压入
operand栈中
*/
//(4+5)*2*4/2+3
case calTextArr[i] == ")":
do{
operand.push(operator.pop());
}while(operator.slice(-1)[0] != "(");
operator.pop();
break;
//如果是其他的操作符,则比较优先级后再进行操作
default:
if(operator.length == 0){
operator.push(calTextArr[i]);
}
else if(compareOperator(calTextArr[i],operator.slice(-1)[0])){
do{
operand.push(operator.pop());
var compareResult = compareOperator(calTextArr[i],operator.slice(-1)[0]);
}while(compareResult);
operator.push(calTextArr[i]);
}
else {
operator.push(calTextArr[i]);
}
break;
}
}
}
//遍历结束后,将operator中的元素全部压入operand中
operator.forEach(function(){
operand.push(operator.pop());
});
//在把用于比较的“#”字符去掉
operator.pop();
var nearr = new Array();
for(var i = 0,j = 0;i < operand.length;i++){
if(operand[i] != ""){
nearr[j] = operand[i];
j++;
}
}
return nearr;
}
//--------------------------下面的代码是比较符号优先级的方法
function compareOperator(a,b){
var aLevel = getOperatorRand(a),
bLevel = getOperatorRand(b);
if(aLevel <= bLevel){
return true;
}
else if(aLevel > bLevel){
return false;
}
}
//比较操作符的优先级
function getOperatorRand(operator){
switch(operator){
case "#":
return 0;
case "-":
return 1;
break;
case "+":
return 1;
break;
case "*":
return 2;
break;
case "/":
return 2;
break;
}
}
拿到逆波兰表达式之后我们接下来就是运算
function jieguo(RPNarr){
var result;
while(RPNarr.length > 1)
RPNarr = singleResult(RPNarr);
console.log(RPNarr)
result = RPNarr[0];
return result;
}
//每遇到一个操作符就进行一次运算然后更新数组,直到算出最终结果。
function singleResult(RPNarr){
for(var i = 0,max = RPNarr.length; i < max; i++){
console.log(!Number(RPNarr))
if(!Number(RPNarr[i])){
switch(RPNarr[i]){
case "+":
var addResult = Number(RPNarr[i-2]) + Number(RPNarr[i-1]);
RPNarr.splice(i-2,3,addResult);
return RPNarr;
break;
case "-":
var addResult = Number(RPNarr[i-2]) - Number(RPNarr[i-1]);
RPNarr.splice(i-2,3,addResult);
return RPNarr;
break;
case "*":
var addResult = Number(RPNarr[i-2]) * Number(RPNarr[i-1]);
RPNarr.splice(i-2,3,addResult)
return RPNarr;
break;
case "/":
var addResult = Number(RPNarr[i-2]) / Number(RPNarr[i-1]);
RPNarr.splice(i-2,3,addResult)
return RPNarr;
break;
}
}
}
}
核心内容已经完成了接下来就是一些点击事件和html的简单样式
//--------这里是一些按钮的js代码,没什么说的
//获取显示框
var show_result = document.getElementById("show");
var show_result1 = document.getElementById("show1");
//获取清除键
var clear_btn = document.getElementById("clear");
//获取退格键
var del_btn = document.getElementById("del");
//获取等号
var result_btn = document.getElementById("result");
//获取所有的数字键
var nums = document.getElementsByClassName("num");
//获取所有的操作符键
var czfs = document.getElementsByClassName("czf");
//获取小数点
var dian = document.getElementById("dian");
//定义两个变量来进行存储
var numValue1 = '';
var numValue2 = '';
for(var i = 0;i < nums.length;i++){
nums[i].onclick = function () {
numValue1 += this.innerText;
numValue2 += this.innerText;
show_result.value = numValue2;
}
}
for (var j = 0;j < czfs.length;j++){
czfs[j].onclick = function () {
numValue1 = "";
numValue2 += this.innerText;
show_result.value = numValue2;
}
}
//退格按键
del_btn.onclick = function() {
var i = numValue2.length-1;
var j = numValue1.length-1;
// var nu = numValue1.charAt(i) ; //获取要删除的元素进行判断
if(i >= 1){
numValue2 = numValue2.substring(0,i);
}else {
numValue2 = "";
}
if(j >= 1){
numValue1 = numValue1.substring(0,i);
}else {
numValue1 = "";
}
if(numValue2.length == 0){
show_result.value = 0;
}else {
show_result.value = numValue2;
}
}
function Dian() {
if(numValue1.indexOf(".") == -1){
if(numValue2.length == 0 ){
numValue1 = "0.";
numValue2 = "0.";
}else {
numValue1 += ".";
numValue2 +=".";
}
show_result.value = numValue2;
}
}
//清除全部
clear_btn.onclick =function () {
numValue1 = "";
numValue2 = "";
show_result.value = "0";
show_result1.value = "0";
}
result_btn.onclick = function () {
var s = nbl(numValue2);
var maxnum = jieguo(s).toFixed(5)*1;
show_result.value = maxnum;
show_result1.value = numValue2;
numValue2 = maxnum;
numValue1 = "";
}
最后就是huml和css
// 样式比较丑,别喷,你们可以自己设置设置弄好看一点
Title
C
(
)
/
7
8
9
*
4
5
6
-
1
2
3
+
0
退格
.
=