简单计算器算法思路:能处理小数运算和取模运算,无括号

日常学习中总是能遇到做计算器的时候。今天,我就简单介绍一下我想的表达式求值方法。(有括号的表达式可以通过这个思路延伸出来)

一、分析

数学表达式求值、计算器求值都是根据运算符优先级来进行相应计算的。
怎么处理符号的优先级是非常重要的。

我以前学过用栈来求解表达式,但是需要个复杂的运算符优先级数组,这个数组很难记忆,不方便使用。

但优先级大小完全可以用数值大小来表示,数值也能有优先级。
在这里插入图片描述

二、解决办法

优先级处理:
1、将 *、/ 、%运算符优先级定义为3。(括号优先级可以定为4)
2、将 +、- 运算符优先级定义为2。
3、将数值(1、2.5这种)优先级定义为1。
4、= 号优先级可有可无,想用就设为0。

数值处理
1、0-9正常大小
2、“+”大小为10,“-”大小为11,“*”大小为12,“/”大小为13,“%”大小为14

用两个数组保存主要数据,一切操作围绕数组进行。

通过代码注释讲解

String function(String str){//按下等号
    
    int lg = str.length;	//得到字符串长度
    String ms = str;	//复制字符串
    float ary[20];	//保存数值,(=-*/%)对应(10、11、12、13、14)
    float ary2[20];	//保存优先级	,3、2、1、0
    float s = 0.0;	//储存结果

    int i = 0,j = 0;
    int t = 0;	//表示数值个数,ary数组已使用空间大小
    int flag = 0;	//
    float num = 0.0;	//字符串转浮点数要用
    String temp = "";	//存储得到的数值字符串
    int max = 0;	//比较优先级
    int mf = 0;		
    int left = 0;
    int right = 0;
    
    //遍历字符串,将字符串信息提取为数值数组和优先级数组
    for(i = 0;i < lg;i++) {
      //如果到达字符串结尾,保存最后一位数到ary数组中
      if(i==(lg-1)){
        temp = ms.substring(flag,lg);  //得到对应的数值字符串
        num = parseFloat(temp); //字符串转浮点数
        ary[t] = num; //对应位赋值
        ary2[t] = 1;	//优先级为1
        t++;
      }
      //如果检测到是运算符,得到运算符之前的数并保存,然后保存运算符及其优先级
      if(ms.charAt(i)=="+" || ms.charAt(i)=="-" || ms.charAt(i)=="*" || ms.charAt(i)=="÷" || ms.charAt(i)=="%"){
        temp = ms.substring(flag,i);  //得到对应的数值字符串
        num = parseFloat(temp); //字符串转浮点数
        ary[t] = num; //对应位赋值
        ary2[t] = 1;
        t++;
        switch(ms.charAt(i)){
          case "+":
            ary[t] = 10;	//加号大小定义为10,优先级是2
            ary2[t] = 2;
            break;
          case "-":
            ary[t] = 11;
            ary2[t] = 2;
            break;
          case "*":
            ary[t] = 12;	//乘号大小定义为12,优先级为3,其他类似
            ary2[t] = 3;
            break;
          case "÷":
            ary[t] = 13;
            ary2[t] = 3;
            break;
          case "%":
            ary[t] = 14;
            ary2[t] = 3;
            break;
        }
        flag = i+1; //标记运算符在的位,方便之后得到数
        t++;
      }
    }
    
    //上面得到了二个数组
    //例子:2+3.2*7
    //ary:	2		10		3.2		12		7
    //ary2:	1		2		1		3		1
 	//根据两个数组处理字符串
 	//*********************************************************
 	//找出最高优先级的操作,再找出左右最近的两个操作数(优先级为1)
 	//执行该运算操作
 	//将结果赋值到左操作数上,其他位对应的优先级置0
 	//循环该过程,直到最高优先级为1时结束
 	//此时,表达式只剩下了结果保存在ary[0]中
 	//********************************************************
    for(i = 0;i < t;i++){
      max = 0;
      for(j = 0;j < t;j++){
        if(ary2[j]>max){
          max = ary2[j];
          //left:左操作数下标,right:右操作数下标,mf运算符下标
          left = right = mf = j;	
        }
      }
      
      if(max == 1){
        //结束标志
        return str + "=" + s;
      }
      while(ary2[left]!=1){	//得到左操作数
        left--;
      }
      while(ary2[right]!=1){//d得到右操作数
        right++;
      }
      //执行运算符操作
      switch(ary[mf]){
        case 10:
          s = ary[left] + ary[right] ;
          break;
        case 11:
          console.log(11);
          s = ary[left] - ary[right];
          break;
        case 12:
          console.log(12);
          s = ary[left] * ary[right];
          break;
        case 13:
          console.log(13);
          s = ary[left] / ary[right];
          break;
        case 14:
          console.log(14);
          s = ary[left] % ary[right];
          break;
      }
      ary[left]=s;	//将结果保存在左操作数位置上
      
      for(int k = left+1;k <= right;k++){
        ary2[k] = 0;	//将运算符及右操作数优先级置0
      }
      
    }
    
  }
}
//例子:2+3.2*7	,两个数组最后的值
//ary:	24.4		10		22.4		12		7
//ary2:	1			0		0			0		0

这个算法我就用了2个数组就解决了,今天能想到这个方法,有点小高兴!!

猜你喜欢

转载自blog.csdn.net/qq_44829047/article/details/106580340