当前位置: 首页 > Web前端 > HTML

js实现数学表达式计算,兼容中文数字计算

时间:2023-03-28 12:04:31 HTML

介绍实现数学表达式计算器,涉及两种方法,波兰表示法(维基百科)和逆波兰表示法(维基百科),详细概念可以自己查百科.波兰语表达式是把运算符放在前面,即前缀表达式;逆波兰表达式就是把运算符放在后面,也就是一个后缀表达式。而我们平时输入的叫做中缀表达式。如果我们直接计算中缀表达式,那么判断优先级不是很方便,但是前缀或者后缀写计算逻辑就很方便了。效果说明网上的Demo代码地址实现了idea转换表达式,所以首要任务就是对输入的数学表达式进行转换。这里我选择将中缀转换成后缀表达式来计算,当然前缀也是一样。我们需要声明两个堆栈,一个用于符号,一个用于输出后缀表达式。常量堆栈:字符串[]=[];常量输出:字符串[]=[];首先对输入的表达式字符串进行处理,将其分成数字和符号,存储在同一个数组中。这里我把-(减号)换成了+号,方便后续计算。split支持使用正则表达式来分割字符串。在这里,运算符用于拆分字符串。需要注意的是正则匹配项必须加(),这样split会收集到用于拆分的操作符。constreg=newRegExp(/(\+|\*|x|\/|\(|\))/g);constlist=value.replace(/\-/g,"+-").split(reg);symbolpriority用一个对象来记录symbol的优先级,方便判断是symbol还是数字,以及转换时入栈的先后顺序。priority)<加减法<乘除法<(这里多加了x,因为我想用x来表示乘法,输入时少按一个键exportconstSingle={"+":1,"-":1,"*":2,x:2,"/":2,"(":3,")":-1,};核心转换逻辑方便了我们处理过的列表,空格我没有处理提前,因为不想用filter方便,所以转换的时候要判断,如果str为空,就跳过这个循环;str有两种情况,数字或者运算符:数字很简单,直接push到输出(最后的表达式);如果是运算符,需要根据情况处理,当栈顶没有元素时,直接压入栈运算符栈。直接压入符号栈,因为我是用pop获取栈顶元素,所以必须把栈顶元素推回,如果当前算子的优先级低于t的栈顶元素入栈,将栈顶元素压入表达式栈,然后继续获取栈顶元素。当栈顶元素是(而当前运算符不是)时,需要将(推回,保证括号内表达式的优先级。遇到),(会在这里被pop掉,没有直接判断onstr是否等于(),因为我们事先设置了优先级(具有最高优先级,会直接入栈;)具有最低优先级,遇到左括号后的运算符会处理,而设置index>0的限制,右括号不会入栈。for(leti=0;itopIndex||topIndex===3){stack.push(topValue);堆栈。推(海峡);继续;}else{while(topIndex&&index<=topIndex){if(topIndex<3)output.push(topValue);topValue=stack.pop()||"";topIndex=Single[topValue];//处理括号//topIndex===3表示符号栈顶是(//index>0表示当前搜索的符号不是)//因为符号不是),pop掉线(需要加上返回if(topIndex===3&&index>0){stack.push(topValue);break;}}if(index>0)stack.push(str);}}elseif(/\d/.test(str)){output.push(str);}}计算表达式其实是转换中的主要麻烦表达式,转换完成后就很简单了。后缀表达式的计算逻辑是遇到两个出栈的元素,进行运算。声明计算方法声明计算方法对应的运算符constcounterFn={add:(a:number,b:number)=>a+b,minus:(a:number,b:number)=>a-b,乘法:(a:数字,b:数字)=>a*b,除法:(a:数字,b:数字)=>a/b,};constcounterMap={"+":counterFn.add,"-":counterFn.minus,"*":counterFn.multiply,x:counterFn.multiply,"/":counterFn.divide,};遍历后缀表达式,压栈之间的数,遇到运算符,得到对应的计算方法,输出Stack两个元素进行计算exportfunctioncounter(list:string[]){conststack:number[]=[];让结果=0;for(leti=0;i