javascript四则运算,javascript中解析四则运算表达式
分类:新闻中心

在编写代码时我们有时候会碰到需要自己解析四则运算表达式的情况,本文简单的介绍使用JavaScript实现对简单四则运算表达式的解析。

javascript中解析四则运算表达式的算法和示例,javascript四则运算

在编写代码时我们有时候会碰到需要自己解析四则运算表达式的情况,本文简单的介绍使用JavaScript实现对简单四则运算表达式的解析。

一、熟悉概念

中缀表示法(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4)。也就是我们最常用的算术表达式,中缀表达式对于人类来说比较容易理解,但是不易于计算机解析。

逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。逆波兰记法不需要括号来标识操作符的优先级。逆波兰表示法容易使用堆栈结构对表达式进行解析并计算,所以,这里我们解析四则元素表达式,是先从中缀表达式,转换为逆波兰表达式。然后再计算值。

二、转换流程

中缀表达式转换为后缀表达式(调度场算法)

1.输入队列弹出一个记号
2.如果记号为数字,添加到输出队列中
3.如果是一个操作符(+-*/)则比较它与输出堆栈中栈顶的操作符,如果优先级小于或等于栈顶的操作符,那么将栈顶的操作符弹出并加入输出队列(循环,直到上述条件不满足),最后将本次的操作符压入堆栈。
4.如果是一个左括号,压入堆栈
5.如果是一个右括号,从栈中不断的弹出操作符,并加入输出队列,知道栈顶的元素为左括号。弹出左括号,不加入输出队列。如果没有发现左括号,说明原来的表达式中括号不对称,有错误。
6.如果输入队列为空,而栈中尚有操作符时,如果栈顶的操作符为左括号,则说明原表达式有不匹配的括号。将栈中的操作符逐个弹出,加入输出队列。
7.完成

美高梅游戏官网网站 1

三、转换代码实现

function isOperator(value){
 var operatorString = "+-*/()";
 return operatorString.indexOf(value) > -1
}

function getPrioraty(value){
 switch(value){
  case '+':
  case '-':
   return 1;
  case '*':
  case '/':
   return 2;
  default:
   return 0;
 }
}

function prioraty(o1, o2){
 return getPrioraty(o1) <= getPrioraty(o2);
}

function dal2Rpn(exp){
 var inputStack = [];
 var outputStack = [];
 var outputQueue = [];

 for(var i = 0, len = exp.length; i < len; i++){
  var cur = exp[i];
  if(cur != ' ' ){
   inputStack.push(cur);
  }
 }
 console.log('step one');
 while(inputStack.length > 0){
  var cur = inputStack.shift();
  if(isOperator(cur)){
   if(cur == '('){
    outputStack.push(cur);
   }else if(cur == ')'){
    var po = outputStack.pop();
    while(po != '(' && outputStack.length > 0){
     outputQueue.push(po);
     po = outputStack.pop();
    }
    if(po != '('){
     throw "error: unmatched ()";
    }
   }else{
    while(prioraty(cur, outputStack[outputStack.length - 1]) && outputStack.length > 0){
     outputQueue.push(outputStack.pop());
    }
    outputStack.push(cur);
   }
  }else{
   outputQueue.push(new Number(cur));
  }
 }
 console.log('step two');
 if(outputStack.length > 0){
  if(outputStack[outputStack.length - 1] == ')' || outputStack[outputStack.length - 1] == '('){
   throw "error: unmatched ()";
  }
  while(outputStack.length > 0){
   outputQueue.push(outputStack.pop());
  }
 }
 console.log('step three');
 return outputQueue;

}

console.log(dal2Rpn('1 + 2'));
console.log(dal2Rpn('1 + 2 + 3'));
console.log(dal2Rpn('1 + 2 * 3'));
console.log(dal2Rpn('1 + 2 * 3 - 4 / 5'));
console.log(dal2Rpn('( 1 + 2 )'));

console.log(dal2Rpn('( 1 + 2 ) * ( 3 - 4 ) / 5'));
console.log(dal2Rpn('( 1 + 2 ) * (( 3 - 4 ) / 5)'));

四、逆波兰表达式求值

1.从输入队列中弹出一个记号
2.如果是操作数,加入输出堆栈
3.如果是一个操作符,从输出堆栈中弹出两个操作数并进行计算,并将计算得到的值压入输出堆栈。
4.循环操作,如果输入队列为空,且输出堆栈只有一个数则这个数为结果,否则是出现了多余的操作数。

五、计算代码

function evalRpn(rpnQueue){
 var outputStack = [];
 while(rpnQueue.length > 0){
  var cur = rpnQueue.shift();

  if(!isOperator(cur)){
   outputStack.push(cur);
  }else{
   if(outputStack.length < 2){
    throw "unvalid stack length";
   }
   var sec = outputStack.pop();
   var fir = outputStack.pop();

   outputStack.push(getResult(fir, sec, cur));
  }
 }

 if(outputStack.length != 1){
  throw "unvalid expression";
 }else{
  return outputStack[0];
 }
}

六、结语

逆波兰表示法,在初次接触的时候感觉不太习惯,但是熟悉之后,会发现,其实思路特别简单,不像中缀表示法,还有各种优先级啊,还有小括号之类的,逻辑特别麻烦,还是逆波兰表示法比较简洁,完全不用考虑优先级,也没用小括号,中括号还有大括号搅局。

1、概念

逆波兰表示法也叫后缀表示法,即操作符号都置于操作数的后面,逆波兰表示法可以不用括号来标识操作符的优先级。例如:3+4 是一个中缀表达式,转换成逆波兰表达式为34+ 。有人可能会想有后缀表达式,中缀表达式,那有没有前缀表达式呢?答案是:有前缀表达式,也叫波兰表达式,上文中的3+4 用前缀表达式表示为+34。

波兰式、逆波兰式是《数据结构》课程中讲解关于栈的时候提到的,栈是很简单的一种数据结构。但是这些理论的提出却是计算机早期发展领域的重大突破,值得仔细回味。

一、熟悉概念

设计一个实现四则运算表达式转换与值的演示程序

/*演示程序是啥?这是我们的作业,中缀转后缀求值,比较粗糙,不知道是不,希望对你有用*/
/********本程序中在栈中多增加了一个top_temp指针,用来从栈底遍历栈********/
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define INITSIZE 10
#define SIZE 100
#define OK 1;
#define ERROR 0;
typedef struct{
int oator;
char orand;
}SElemType;
typedef struct{
SElemType *base;
SElemType *top;
SElemType *top_temp;
int stacksize;
}SqStack;
int InitStack(SqStack *S)
{
S->base=(SElemType *)malloc(SIZE * sizeof(SElemType));
if(!S->base) exit(0);
S->top_temp=S->top=S->base;
S->stacksize=SIZE;
return OK;
}
int Push_oator(SqStack *S,int Oat) //插入栈顶元素算法,整型
{
if(S->top-S->base>=SIZE)
{
S->base=(SElemType *)realloc(S->base,INITSIZE * sizeof(SElemType));
S->top=S->base+S->stacksize;
S->stacksize+=INITSIZE;
}
S->top->oator=Oat;
S->top->orand=0;
S->top++;
return OK;
}
int Push_orand(SqStack *S,char Orand) //插入栈顶元素,字符型
{
if(S->top-S->base>=SIZE)
{
S->base=(SElemType *)realloc(S->base,INITSIZE * sizeof(SElemType));
S->top=S->base+S->stacksize;
S->stacksize+=INITSIZE;
}
S->top->orand=Orand;
S->top->oator=0;
S->top++;
return OK;
}
int GetTop(SqStack *S) //取栈顶元素,返回值为栈顶元素的值
{
if(S->top==S->base) exit(0);
if((S->top-1)->oator==0&&(S->top-1)->orand!=0) //若为操作符
return (S->top-1)->orand; //返回字符
if((S->top-1)->oator!=0&&(S->top-1)->orand==0) //若为操作符
retu......余下全文>>  

2、用途

1.逆波兰表达式中不需要括号,用户只需按照表达式顺序求值,让堆栈自动记录中间结果;同样的,也不需要指定操作符的优先级
2.机器状态永远是一个堆栈状态,堆栈里是需要运算的操作数,栈内不会有操作符。
3.当有操作符时就计算,因此,表达式并不是从右至左整体计算而是每次由中心向外计算一部分,这样在复杂运算中就很少导致操作符错误。

1. 中缀表达式

我们在数学中学到的表达式被称为中缀表达式,操作符号在操作数中间,比如 2 + 3 * (5 - 1)。对人类而言,这种表达方式显而易见,求值也很直接,先算乘除再算加减,先算括号内再算括号外。

然而,这个表达式对于计算机而言却很费解。你可能会有疑问:这有什么难理解的嘛,在JavaScript、Python或者Ruby,甚至是Java里面都可以通过eval("2 + 3 * (5 - 1)")来计算这个表达式。当然,这里的计算机并不是指现而今强大的计算机和高级编程语言,而是指上个世纪中页还处于发展初期的计算机。

中缀表示法(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4)。也就是我们最常用的算术表达式,中缀表达式对于人类来说比较容易理解,但是不易于计算机解析。

C++程序设计:四则混合运算表达式的解析与计算

double PostCalculate::calculate(std::string *p,int size)
{
std::stack<string> a;
std::string postExp[20];
int count=0; //对 后缀表达式 计数
for(int i=0;i<size;i++)
{
if(!isSign(p)) //若不是符号 ,即为数字
{
postExp[count]=*p; //将数字直接放入后缀表达式
count++;
}

else if(*p=="+" ||*p=="-")
{
while(!a.empty() && a.top()!="(") //弹出栈中元素直到 栈空 或者 左括号
{
postExp[count]=a.top();
count++;
a.pop();
}
a.push(*p); //将当前元素压栈
}
else if(*p=="*" || *p=="/")
{
while(!a.empty() && a.top()!="(" && a.top()!="+" && a.top()!="-")
{
postExp[count]=a.top();
count++;
a.pop();
}
a.push(*p);
}
else if(*p=="(")
{
a.push(*p);
}
else if(*p==")")
{
while(!a.empty() && a.top()!="(")
{
postExp[count]=a.top();
count++;
a.pop();
}
if(!a.empty() && a.top()=="(")
a.pop();
}
p++;
}
while(!a.empty())
{
postExp[count++]=a.top();
a.pop();
}
double result=postCal(postExp,count);
return result;
}
std::string PostCalculate::dispose(std::string first, std::string second, std::string op)
{
stringstream t;
double r;
double a=stringToDouble(first);
double b=stringToDouble(second);
if(op=="+")
r=a+b;
else if(op=="-")
r=a-b;
else if(op=="*")
r=a*b;
else if(op=="/")
r=a/b;
t......余下全文>>  

在编写代码时我们有时候会碰到需要自己解析四则运算表达式的情况,本文...

3、计算原理

逆波兰表达式进行数据计算的时候一般分为两步:
1.将中缀表达式转换为后缀表达式
2.对转换完成后的后缀表达式进行计算

例子:我们以a+b-c*(d+e) 来进行分析

2. 前缀表达式

早在1920年,波兰科学家扬·武卡谢维奇就发明了一种不需要括号的表示法,可以用来表示一个计算表达式。即将操作符号写在操作数之前,也就是前缀表达式,即波兰式(Polish Notation, PN)。这种表达式直到1960年计算机出现后才发挥出其威力。

比如2 + 3 * (5 - 1)这个表达式的前缀表达式为+ 2 * 3 - 5 1来表示。

阅读这个表达式需要从左至右读入表达式,如果一个操作符后面跟着两个操作数时,则计算,然后将结果作为操作数替换这个操作符和两个操作数,重复此步骤,直至所有操作符处理完毕。从左往右依次读取,直到遇到- 5 1,做计算后,将表达式替换为+ 2 * 3 4,然后从左往右再次读取,直到遇到* 3 4,做计算后将表达式替换为+ 2 12,然后从左往右依次读取,读到+ 2 12,计算得到14,到此结束。

可以看到,这种计算过程也相当复杂,需要多次遍历表达式,而且需要识别一个操作符后面跟着两个操作数这种模式,相比而言,下文中的逆波兰式要更为直接和简单。

如果你熟悉各种编程语言的话,这很像Lisp语言中的表达式(如下代码)。需要注意的是,Lisp语言中的括号并不是数学意义上的的括号,Lisp中的函数是可以携带多个参数的,比如(+ 1 2 3),因此需要使用括号来标明函数参数。

Clojure1.5.1
user=>(+2(*3(-51)))14

逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。逆波兰记法不需要括号来标识操作符的优先级。逆波兰表示法容易使用堆栈结构对表达式进行解析并计算,所以,这里我们解析四则元素表达式,是先从中缀表达式,转换为逆波兰表达式。然后再计算值。

3.1 将其转换为后缀表达式

.首先我们要建立一个集合 sList 来存放例子中的数据和操作符号,一个栈opStack来存放中间的操作符号,一个集合dList 来存放最后的转换结果。
2.从sList中取出一个元素A然后进行以下判断:
1.如果A是数字,则直接存如dList
2.如果A是运算符,则和opStack栈顶的元素进行运算优先级比较
1.如果A的优先级高于栈顶运算符优先级,则将A入栈opStack
2.如果A的优先级低于或等于栈顶运算符的优先级,那么将栈顶的元素出栈存入dList,重复此步骤直到栈顶的运算符优先级低于当前运算符(或者遇到括号),然后A入栈。
3.如果A是左括号“(”直接入栈,如果是右括号“)”,则将opStack中的运算符弹出存入dList,直到弹出左括号,左右括号均不存入dList,左括号永远不会弹出,直到遇到右括号。
4.不断重复以上步骤直到表达式解析完成。

下面来看一下上面的具体例子:a+b-c*(d+e)

dList opStack 解释
{} {}
{a} {} a 加入dList
{a} {+} + 入栈
{a,b} {+} b 加入dList
{a,b,+} {-} +号出栈,-号入栈
{a,b,+,c} {-} c 加入dList
{a,b,+,c} {-,*} 因为* 的优先级高于- 则将* 直接入栈
{a,b,+,c} {-,*,(} 左括号直接入栈
{a,b,+,c,d} {-,*,(} d 加入dList
{a,b,+,c,d} {-,*,(,+} + 直接入栈
{a,b,+,c,d,e} {-,*,(,+} e 直接加入dList
{a,b,+,c,d,e,+} {-,*} 将左括号之上的符号出栈加入dList
{a,b,+,c,d,e,+,*,-} {} 将栈中的剩余元素弹出

将dList 中的元素输出,则得到后缀表达式:ab+cde+*美高梅游戏官网网站,-

3. 后缀表达式

后缀表达式也称为逆波兰式(Reverse Polish Notation, RPN),更加广为人知一些,和前缀表达式刚好相反,是将操作符号放置于操作数之后,比如2 + 3 * (5 - 1)用逆波兰式来表示则是:2 3 5 1 - * +

逆波兰式的计算也是从左往右依次读取,当读到操作符时,将之前的两个操作数做计算,然后替换这两个操作数和操作符,接着读取,重复此步骤。对于这个表达式,读到5 1 -,得到4,然后读取乘号,取出前面的3和上一步的计算结果4,并计算,到12,接着读取加号+,计算2 12 +得到14,计算结束。

上面这个步骤可以很容易的用栈来实现:

从左往右依次读取表达式,如果是数字则将该数字压栈,如果是符号,则将之前的两个数字出栈,做计算后,将计算结果压栈,直到表达式读取结束。栈中剩下的一个数就是计算结果。

逆波兰式看起来像波兰式反过来,比如5 + 1的波兰式是+ 5 1,逆波兰式为5 1 +或者1 5 +。也很明显,逆波兰式并不是简单的将波兰式反过来,因为,减法和除法中减数和被减数、除数与被除数是不能交换的,即- 10 5- 5 10就完全不一样。

二、转换流程

3.2 用后缀表达式来计算结果

首先建立一个结果栈rStack,然后将dList中的元素依次取出,进行入栈操作,如果碰到操作符就从栈中取出两个元素进行运算,结果入栈,依次重复。

下面接着看上面的例子
dList {a,b,+,c,d,e,+,*,-}

rStack

{ } 
{a}   //a入栈 
{a,b} //b入栈 
{a+b} //遇到+号,取出两个操作数进行运算,运算结果入栈 
{a+b,c} 
{a+b,c,d} 
{a+b,c,d,e} 
{a+b,c,d+e} 
{a+b,c*(d+e)} 
{a+b-c*(d+e)} 

计算结果:a+b-c*(d+e)

4. 中缀表达式到后缀表达式的转换

因为通过后缀表达式来进行计算只需要一个栈即可,从硬件和软件上实现都是极为便利的,因此逆波兰式在计算机领域的应用更加广泛,因此将中缀表达式转换为逆波兰式非常重要。

依然仅仅使用栈就可以将中缀表达式转换成逆波兰式,转换过程如下:

从左往右遍历中缀表达式中的每个数字和符号,弱是数字就输出,成为逆波兰式的一部分; 如果是右括号,或者是其他符号并且比当前栈顶符号的优先级低,则栈顶元素依次出栈并输出; 然后将当前符号进栈,重复以上操作直到结束。

还是以2 + 3 * (5 - 1)为例:

  1. 首先读入数字2,直接将其输出,输出为2,栈为空
  2. 接着读入加号+,由于栈为空,因此将其进栈,输出为2,栈为+
  3. 接着读入数字3,直接将其输出,输出为2 3,栈为+
  4. 接着读入乘号*,比栈顶元素优先级高,进栈,输出为2 3,栈为+ *
  5. 读入左括号(,直接进栈,输出2 3,栈为+ * (
  6. 读入数字5,直接将其输出,输出为2 3 5,栈为+ * (
  7. 读入减号-,栈顶元素为左括号,进栈,输出为2 3 5,栈为+ * ( -
  8. 读入数字1,直接将其输出,输出为2 3 5 1,栈为+ * ( -
  9. 读入右括号,依次输出栈顶元素,直到左括号,括号不输出,输出2 3 5 1 -,栈为+ *
  10. 已经无元素可读,依次输出栈顶元素,直到栈为空,输出2 3 5 1 - * +,栈为空

这样可以仅仅使用栈,首先将中缀表达式转换为逆波兰式,然后用本文第3节中的方法对后缀表达式进行求值,整个过程使用栈来完成即可。

中缀表达式转换为后缀表达式(调度场算法)

4、巩固练习:

写出a*(b-c*d)+e-f/g*(h+i*j-k)的逆波兰表达式。

答案:

abcd*-*e+fg/hij*+k-*-

5. 表达式树与逆波兰式

还可以通过另外一种方法来将一个表达式转换成波兰式和逆波兰式,这种方法依赖与树,首先需要根据表达式构建成树,仍然以2 + 3 * (5 - 1)为例,下图是其表达式树。

美高梅游戏官网网站 2

我们发现这个树的后序遍历结果为2 3 5 1 - * +,刚好是其逆波兰式;而其先序遍历结果为+ 2 * 3 - 5 1刚好为其波兰式;中序遍历就不用说了,就是我们常见的中缀表达式。我们也可以通过这种特性来实现表达式的各种表示方法的转换。

1.输入队列弹出一个记号
2.如果记号为数字,添加到输出队列中
3.如果是一个操作符(+-*/)则比较它与输出堆栈中栈顶的操作符,如果优先级小于或等于栈顶的操作符,那么将栈顶的操作符弹出并加入输出队列(循环,直到上述条件不满足),最后将本次的操作符压入堆栈。
4.如果是一个左括号,压入堆栈
5.如果是一个右括号,从栈中不断的弹出操作符,并加入输出队列,知道栈顶的元素为左括号。弹出左括号,不加入输出队列。如果没有发现左括号,说明原来的表达式中括号不对称,有错误。
6.如果输入队列为空,而栈中尚有操作符时,如果栈顶的操作符为左括号,则说明原表达式有不匹配的括号。将栈中的操作符逐个弹出,加入输出队列。
7.完成

6. 参考

  • 逆波兰表示法
  • 波兰表示法
  • 调度场算法
  • 将表达式转换成逆波兰式

美高梅游戏官网网站 3

三、转换代码实现

function isOperator(value){
 var operatorString = "+-*/()";
 return operatorString.indexOf(value) > -1
}

function getPrioraty(value){
 switch(value){
  case '+':
  case '-':
   return 1;
  case '*':
  case '/':
   return 2;
  default:
   return 0;
 }
}

function prioraty(o1, o2){
 return getPrioraty(o1) <= getPrioraty(o2);
}

function dal2Rpn(exp){
 var inputStack = [];
 var outputStack = [];
 var outputQueue = [];

 for(var i = 0, len = exp.length; i < len; i++){
  var cur = exp[i];
  if(cur != ' ' ){
   inputStack.push(cur);
  }
 }
 console.log('step one');
 while(inputStack.length > 0){
  var cur = inputStack.shift();
  if(isOperator(cur)){
   if(cur == '('){
    outputStack.push(cur);
   }else if(cur == ')'){
    var po = outputStack.pop();
    while(po != '(' && outputStack.length > 0){
     outputQueue.push(po);
     po = outputStack.pop();
    }
    if(po != '('){
     throw "error: unmatched ()";
    }
   }else{
    while(prioraty(cur, outputStack[outputStack.length - 1]) && outputStack.length > 0){
     outputQueue.push(outputStack.pop());
    }
    outputStack.push(cur);
   }
  }else{
   outputQueue.push(new Number(cur));
  }
 }
 console.log('step two');
 if(outputStack.length > 0){
  if(outputStack[outputStack.length - 1] == ')' || outputStack[outputStack.length - 1] == '('){
   throw "error: unmatched ()";
  }
  while(outputStack.length > 0){
   outputQueue.push(outputStack.pop());
  }
 }
 console.log('step three');
 return outputQueue;

}

console.log(dal2Rpn('1 + 2'));
console.log(dal2Rpn('1 + 2 + 3'));
console.log(dal2Rpn('1 + 2 * 3'));
console.log(dal2Rpn('1 + 2 * 3 - 4 / 5'));
console.log(dal2Rpn('( 1 + 2 )'));

console.log(dal2Rpn('( 1 + 2 ) * ( 3 - 4 ) / 5'));
console.log(dal2Rpn('( 1 + 2 ) * (( 3 - 4 ) / 5)'));

四、逆波兰表达式求值

1.从输入队列中弹出一个记号
2.如果是操作数,加入输出堆栈
3.如果是一个操作符,从输出堆栈中弹出两个操作数并进行计算,并将计算得到的值压入输出堆栈。
4.循环操作,如果输入队列为空,且输出堆栈只有一个数则这个数为结果,否则是出现了多余的操作数。

五、计算代码

function evalRpn(rpnQueue){
 var outputStack = [];
 while(rpnQueue.length > 0){
  var cur = rpnQueue.shift();

  if(!isOperator(cur)){
   outputStack.push(cur);
  }else{
   if(outputStack.length < 2){
    throw "unvalid stack length";
   }
   var sec = outputStack.pop();
   var fir = outputStack.pop();

   outputStack.push(getResult(fir, sec, cur));
  }
 }

 if(outputStack.length != 1){
  throw "unvalid expression";
 }else{
  return outputStack[0];
 }
}

六、结语

逆波兰表示法,在初次接触的时候感觉不太习惯,但是熟悉之后,会发现,其实思路特别简单,不像中缀表示法,还有各种优先级啊,还有小括号之类的,逻辑特别麻烦,还是逆波兰表示法比较简洁,完全不用考虑优先级,也没用小括号,中括号还有大括号搅局。

您可能感兴趣的文章:

  • JS笛卡尔积算法与多重数组笛卡尔积实现方法示例
  • javascript笛卡尔积算法实现方法
  • JavaScript求一组数的最小公倍数和最大公约数常用算法详解【面向对象,回归迭代和循环】
  • JavaScript实现的贝塞尔曲线算法简单示例
  • javascript常用经典算法实例详解
  • 原生js的RSA和AES加密解密算法
  • JS常用加密编码与算法实例总结
  • JS随机洗牌算法之数组随机排序
  • JavaScript笛卡尔积超简单实现算法示例

本文由美高梅网址发布于新闻中心,转载请注明出处:javascript四则运算,javascript中解析四则运算表达式

上一篇:js实现网页检测是否安装了,javascript检查浏览器 下一篇:没有了
猜你喜欢
热门排行
精彩图文