精华内容
下载资源
问答
  • 可以一次性输入计算公式进行计算 含有多种计算公式如平方,开方等
  • 公式计算器 自定义公式输入计算

    热门讨论 2011-07-08 13:37:38
    可以自己输入公式,各种自己输可以。 还能很方便定义变量
  • 数学公式自动计算器是一款不错数学公式计算软件,使用它可以直接计算四则运算练习题,需要朋友欢迎前来下载使用! 使用方法: 1. 输入公式,比如:(88844-11199)/188 123*8 2. 点击“计算”按纽,自动计算...
  • 电费计算器输入功率和使用时间以及电费价格就可以计算出一天,一月,一年大概费用。
  • 菲涅耳公式计算器

    2019-02-25 13:42:30
    计算光学界面折反射菲涅尔公式工具。输入界面折射率和入射角,可以获得P光反射率和S光反射率具体数值,还可获得全反射临界角、P光与S光相位关系
  • 前一段时间,为了满足公司web...另外,还对页面的输入,数据有效位数等进行了处理,每个数据字段有效位数,开发人员都可以自定义。   该公式解析计算器的具体使用例子,在我另外一篇博客文章中(http://h

    前一段时间,为了满足公司的web报表系统的需求,利用javascript开发了一个自定义公式解析计算器。开发人员可以根据一定规则,自定义web页面元素或者json字段之间的公式关系,实现算术运算和一些逻辑运算。

     

    另外,还对页面的输入,数据的有效位数等进行了处理,每个数据字段的有效位数,开发人员都可以自定义。

     

    该公式解析计算器的具体使用的例子,在我另外一篇博客文章中(http://huangyuanmu.iteye.com/admin/blogs/469180),有兴趣的话,可以看看。

     

    下边给出具体实现代码:

    /**
     *  模拟java的包,或者C#中的命名空间的概念
     * */
    var tohot = tohot ? tohot : {};
    tohot.commons = tohot.commons ? tohot.commons : {};
    tohot.commons.declaration = tohot.commons.declaration ? tohot.commons.declaration : {};
    /**
     * 报表公式计算器实现
     */
    var tohotCalculator = tohot.commons.declaration.ExpressionCalculator = tohot.commons.declaration.ExpressionCalculator ? tohot.commons.declaration.ExpressionCalculator : {
    
    	description : "通用web报表公式解析计算器,根据自定义的报表计算公式,自动进行公式解析和报表数据计算,操作web报表页面数据和json数据。",
    	author : "huangyuanmu",
    	version : "1.0(2009-07-29)",
    
    	report : {},
    
    	// 根据公式,获取计算以后的值
    	getValue : function(report,formular_str,dataType)
    	{
    
    		// 解析公式
    		function _parseFormular() {
    			if (mathing_begin)
    	          {
    	            mathing_str += formular_str.substr(i,1);
    	            return true;
    	          }
    	          else
    	          {
    	            if (IsVar)
    	            {
    	              formular_str_ana += ")";
    	              CurVar_Length += ")".length;
    	              //判断当前的变量的值是否为空
    	              tmpEl = eval(formular_str_ana.substr(CurVar_start,CurVar_Length));
    	              if (isNaN(tmpEl))
    	              {
    	                formular_str_ana = formular_str_ana.substr(0,CurVar_start);
    	                formular_str_ana += "0";
    	              }
    	            }
    	            formular_str_ana += formular_str.substr(i,1);
    	            IsVar = false;
    	            return true;
    	          }
    	          return false;
    		}
    
    	    var formular_str_ana;
    	    var returnValue;
    	    var IsVar;   //表示该处的字符表示变量
    	    var CurVar_start,CurVar_Length;   //表示当前的变量型字符串
    	    var mathing_begin = false;   //字符串的匹配操作是否开始
    	    var mathing_str = "";  //接受并解析匹配字符串
    	    returnValue = 0;
    	    IsVar = false;
    	    var el_chang  =  "report.";
    	    formular_str_ana = "";
    
    	    if(dataType == null){
    	    	dataType = "2";
    	    }
    
    	    for (i = 0;i<formular_str.length;i++)
    	    {
    	      switch(formular_str.substr(i,1))
    	      {
    	        case "$":
    	        {
    	          if (mathing_begin)
    	          {
    	            mathing_str += formular_str.substr(i,1);
    	            break;
    	          }
    	          else
    	          {
    	            //变量的开始
    	            CurVar_start = formular_str_ana.length;
    	            formular_str_ana +=  "parseFloat("  + el_chang;
    	            CurVar_Length = ("parseFloat(" + el_chang).length;
    	            IsVar = true;
    	            break;
    	          }
    	        }
    	        case "@":
    	        {
    	          //匹配字符串的解释
    	          if (mathing_begin)
    	          {
    	            //匹配字符串结束
    	            mathing_begin = false;
    	            mathing_str_arr = mathing_str.split(";");
    	            formular_str_ana += "/^" + mathing_str_arr[0] + "$/i.test(";
    	            if (mathing_str_arr[1].substr(0,1)  == "$")
    	            {
    	              formular_str_ana += "report" + "." + mathing_str_arr[1].substr(1,mathing_str_arr[1].length-1) + ")";
    	            }
    	            else
    	            {
    	              //非变量
    	              formular_str_ana += "'" + mathing_str_arr[1].substr(0,mathing_str_arr[1].length) + "')";
    	            }
    	          }
    	          else
    	          {
    	            //匹配字符串开始
    	            mathing_begin = true;
    	            mathing_str = "";
    	          }
    	          break;
    	        }
    	        case "+":
    	        {
    				if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "-":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "*":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "/":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "%":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case ")":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "?":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case ":":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "<":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "=":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case ">":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "!":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "|":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        case "&":
    	        {
    	          if(_parseFormular()) {
    					break;
    				}
    	        }
    	        default:
    	        {
    	          if (mathing_begin)
    	          {
    	            mathing_str += formular_str.substr(i,1);
    	            break;
    	          }
    	          else
    	          {
    	            if (IsVar)
    	            {
    	              CurVar_Length++;
    	            }
    	            formular_str_ana += formular_str.substr(i,1);
    	          }
    	        }
    	      }
    	    }
    	    if (IsVar)
    	    {
    	      formular_str_ana += ")";
    	      CurVar_Length += ")".length;
    	      //判断当前的变量的值是否为空
    	      tmpEl = eval(formular_str_ana.substr(CurVar_start,CurVar_Length));
    	      if (isNaN(tmpEl))
    	      {
    	        formular_str_ana = formular_str_ana.substr(0,CurVar_start);
    	        formular_str_ana += "0";
    	      }
    	      IsVar = false;
    	    }
    	    if (mathing_begin)
    	    {
    	      //匹配字符串结束
    	      mathing_begin = false;
    	      mathing_str_arr = mathing_str.split(",");
    	      formular_str_ana += "/" + mathing_str_arr[0] + "/i.test(";
    	      if (mathing_str_arr[1].substr(0,1) == "$")
    	      {
    	        formular_str_ana += "report" + "." + mathing_str_arr[1].substr(1,mathing_str_arr[1].length-1) + ")";
    	      }
    	      else
    	      {
    	        //非变量
    	        formular_str_ana += "'" + mathing_str_arr[1].substr(0,mathing_str_arr[1].length) + "')";
    	      }
    	    }
    	    returnValue = eval(formular_str_ana);
    	    // 如果公式计算的值小于0.005,则认为为零
    	    if (Math.abs((returnValue - 0.00))<0.005)
    	    {
    	    	returnValue = tohotCalculator.formatData("0",dataType);
    	    }else{
    			returnValue = tohotCalculator.formatData(returnValue + "",dataType);
    	    }
    	    return returnValue;
    	},
    
    	// 格式化整数
    	formatInteger: function (IntegerStr){
    	    //获取字符串的长度和首字符和次字符,然后进行判断
    	    var strLen = IntegerStr.length;
    	    var firstStr = IntegerStr.substr(0,1);
    	    var secondStr = IntegerStr.substr(1,1);
    	    var tmpStr = IntegerStr;
    	    //针对正数的处理
    	    if(firstStr != "-"){
    	      if ((firstStr == "0") && (strLen > 1)){
    	        tmpStr = tmpStr.substr(1,strLen-1);
    	        tmpStr = tohotCalculator.formatInteger(tmpStr);
    	      }
    	    }
    	    else{
    	      //负数的处理
    	      if((secondStr == "0") && (strLen > 2)){
    	        tmpStr = "-" + tmpStr.substr(2,strLen-2);
    	        tmpStr = tohotCalculator.formatInteger(tmpStr);
    	      }
    	    }
    	    return tmpStr;
    	},
    
    	 // 格式化浮点数
    	 formatFloat: function (FloatStr){
    	    //将字符串组合成整数部分和小数部分
    	    var FloatStrArr = FloatStr.split(".");
    	    var Integer_part = FloatStrArr[0];
    	    var Float_part = FloatStrArr[1];
    	    var FloatPartLen = Float_part.length;
    	    //处理整数部分
    	    if((Integer_part == "-") || (Integer_part == "")){
    	      Integer_part += "0";
    	    }
    	    Integer_part = tohotCalculator.formatInteger(Integer_part);
    	    //处理小数部分
    	    if(FloatPartLen == 0){
    	      Float_part += "00";
    	    }
    	    else{
    	      if(FloatPartLen == 1){
    	        Float_part += "0";
    	      }
    	    }
    	    //合并
    	    return (Integer_part + "." + Float_part);
    	},
    
    	// 数据验证,并设置json对象元素的值
    	formatData: function (DataStr,DataType){
    		var returnValue = "0.00";
    		var IntegerCode,FloatCode;//数字的整数验证码和小数验证码
    	    IntegerCode = /^[-]?[0-9]+$/i; //整数
    	    FloatCode = /^[-]?[0-9]*[.][0-9]+$/i;
    	    //整数
    	    if (DataStr != ""){
    			    if(DataType == "1")
    			    {
    			      if (DataStr.match(IntegerCode) == null)
    			      {
    			        if ((DataStr.match(FloatCode) == null))
    			           {
    			           	 returnValue = "0";
    			           }
    			           else{
    			           	 var reVal = parseFloat(tohotCalculator.formatFloat(DataStr));
    			             returnValue = ""+reVal.toFixed(0);
    			           }
    			      }
    			      else{
    			        returnValue = tohotCalculator.formatInteger(DataStr);
    			      }
    			    }
    			    else if((DataType == "2") || (DataType == "3") || (DataType == "4"))
    			         {
    			          if (DataStr.match(IntegerCode) == null)
    			     		 {
    				           if ((DataStr.match(FloatCode) == null))
    				           {
    				           	 if(DataType == "2")
    			     	   			returnValue = "0.00";
    			     	   		if(DataType == "3")
    			     	   			returnValue = "0.0000";
    			     	   		if(DataType == "4")
    			     	   			returnValue = "0.000000";
    				           }
    				           else{
    				           	 var reVal = parseFloat(tohotCalculator.formatFloat(DataStr));
    				             returnValue = reVal.toFixed(parseInt(DataType)+ (parseInt(DataType) - 2));
    				           }
    				         }
    						else{
    							if(DataType == "2")
    			     	   			returnValue = tohotCalculator.formatInteger(DataStr + ".00");
    			     	   		if(DataType == "3")
    			     	   			returnValue = tohotCalculator.formatInteger(DataStr + ".0000");
    			     	   		if(DataType == "4")
    			     	   			returnValue = tohotCalculator.formatInteger(DataStr + ".000000");
    			     		 }
    			     	}else{
    				           returnValue = "0.00";
    				         }
    
    	    }else{
    	    	if(DataType == "1"){
    	    	  	returnValue = "0";
    	    	}else if(DataType == "2"){
    			    returnValue = "0.00";
    		   	}else if(DataType == "3"){
    		   		returnValue = "0.0000";
    		   	}else if(DataType == "4"){
    		   		returnValue = "0.000000";
    		   	}else{
    		   		 returnValue = "0.00";
    		   	}
    	    }
    	    return returnValue;
    	},
    
    	doCalculateFormular : function (formular) {
    
    		var formualr_is_arr = /[,]/i;
    
    		//解析公式
    	      if (formular.match(formualr_is_arr) == null)
    	      {
    	        //单个公式
    	        each_formular_arr = formular.split("^");
    	        // 解析目标json值的有效位数
    		    var targetArray = each_formular_arr[1].split("#");
    	        // 设置报表json对象的值
    	        var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
    	        eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
    			// 设置页面元素的值
    	        var el = eval(each_formular_arr[0]);
    	    	el.value = value;
    	      }
    	      else
    	      {
    	        //公式数组
    	        all_formular_arr = formular.split(",");
    	        for (k=0;k<all_formular_arr.length;k++)
    	        {
    	          //单个公式
    	          	each_formular_arr = all_formular_arr[k].split("^");
    	          	// 解析目标json值的有效位数
    		    	var targetArray = each_formular_arr[1].split("#");
    	        	// 设置报表json对象的值
    	        	var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
    		        eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
    				// 设置页面元素的值
    		        var el = eval(each_formular_arr[0]);
    		    	el.value = value;
    	        }
    	      }
    	},
    
    	// 计算整个json报表对象,在保存报表的时候调用
    	doCalculateJson : function (reportFormular) {
    
    		_calculatorJson(reportFormular);
    
    		// 计算报表json对象的公式触发
    		function _calculatorJson(reportFormular) {
    			var EachArrStr = "";
    		    var FoumularArr; //公式数组
    		    var formualr_is_arr = /[,]/i;
    		    var e1;
    
    			//解析公式
    			for(key in reportFormular){
    				formular = reportFormular[key];
    				if (formular.match(formualr_is_arr) == null)
    				{
    				    //单个公式
    					each_formular_arr = formular.split("^");
    					// 解析目标json值的有效位数
    		        	var targetArray = each_formular_arr[1].split("#");
    					var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
    					eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
    				}
    				else
    				{
    				    //公式数组
    					all_formular_arr = formular.split(",");
    					for (k=0;k<all_formular_arr.length;k++)
    					{
    					  	//单个公式
    					  	each_formular_arr = all_formular_arr[k].split("^");
    					  	// 解析目标json值的有效位数
    		        		var targetArray = each_formular_arr[1].split("#");
    						var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
    					 	eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
    					}
    				}
    			}
    		}
    	},
    
    	// 根据公式计算当前页面的表单元素的值,在页面onblur事件的时候调用
    	doCalculateCurr : function (cur_el_name,el_value,formular,DataType){
    
    		_calculatorCurr(cur_el_name,el_value,formular,DataType);
    
    		// 计算当前页面的公式触发
    		function _calculatorCurr(cur_el_name,el_value,formular,DataType)
    		{
    		    var EachArrStr = "";
    		    var FoumularArr; //公式数组
    		    var formualr_is_arr = /[,]/i;
    		    var e1;
    		    if(_dataAuth(cur_el_name,el_value,DataType))
    		    {
    		      //解析公式
    		      if (formular.match(formualr_is_arr) == null)
    		      {
    		        //单个公式
    		        each_formular_arr = formular.split("^");
    
    		        // 解析目标单元格的有效位数
    		        var targetArray = each_formular_arr[1].split("#");
    
    		        // 设置报表json对象的值
    			    var form_el_value = tohotCalculator.formatData(el_value,DataType);
    			    eval("tohotCalculator.report." + cur_el_name + "=form_el_value");
    
    		        var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
    		        eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
    				// 设置页面元素的值
    		        var el = eval(each_formular_arr[0]);
    		    	el.value = value;
    		      }
    		      else
    		      {
    		        //公式数组
    		        all_formular_arr=formular.split(",");
    		        for (k=0;k<all_formular_arr.length;k++)
    		        {
    		          //单个公式
    		          	each_formular_arr = all_formular_arr[k].split("^");
    
    		          	// 解析目标单元格的有效位数
    		        	var targetArray = each_formular_arr[1].split("#");
    
    		          	// 设置报表json对象的值
    			        var form_el_value = tohotCalculator.formatData(el_value,DataType);
    			    	eval("tohotCalculator.report." + cur_el_name + "=form_el_value");
    
    			        var value = tohotCalculator.getValue(tohotCalculator.report,targetArray[0],targetArray[1]);
    			        eval("tohotCalculator.report." + each_formular_arr[0] + "=value");
    					// 设置页面元素的值
    			        var el = eval(each_formular_arr[0]);
    			    	el.value = value;
    		        }
    		      }
    		    }
    		}
    
    		// 数据验证,并设置页面元素的值
    		function _dataAuth(DataStr_el_name,DataStr,DataType){
    			var DataStr_el = eval(DataStr_el_name);
    			DataStr_el.value = tohotCalculator.formatData(DataStr,DataType);
    		    return true;
    		}
    	}
    }
    展开全文
  • 海伦公式计算器.rar

    2019-07-03 10:51:41
    用C#编写一个计算器,该计算器可以根据三角形三个边采用海伦公式,计算出每个边高;也可以根据三棱锥(四面体)三条斜边和三个底边,采用海伦秦九韶体积公式计算出该三棱锥(四面体)底边面积、体积和底...
  • 易算数学公式计算器(易算器)是一款非常简单好用的公式计算器,您可以使 用并保存带变量的公式,在运行时只需要在变量列表中填入数据,就可以生 成结果列表,相信使用它可以减少您许多重复工作。 1 可以计算一般代数...
  • 红尖椒公式计算器一般操作说明: 在框内连续输入公式,如:1 2.5-36.25 2*3 在"=" 后会实时得出结果; 在输入公式时,如果结果没有实时变化,请检查公式正确与否; 可以移动光标后直接修改; 如果要清除全部公式内容,请按...
  • 应编译原理课程设计要求,做了一个简易的计算器。项目基于Qt5.13.2开发。语法分析采用LL(1)递归下降文法。该计算器除了可以实现+、-、*、/功能之外,还可以对一些特殊函数以及字符进行运算,比如PI,e,sin,cos,...

    应编译原理课程设计要求,做了一个简易的计算器。项目基于Qt5.13.2开发。语法分析采用LL(1)递归下降文法。该计算器除了可以实现+、-、*、/功能之外,还可以对一些特殊函数以及字符进行运算,比如PI,e,sin,cos,log等等。在计算器界面中除了可以按下按钮进行相应计算,还可以通过键盘来进行输入计算。

    参考资料

    视频链接

    使用的开发工具

    运行环境:Qt 5.13.2
    编程语言:C++

    界面的设计

    新建工程

    Step1:点击New Project

    在这里插入图片描述
    Step2:选择Application里的Qt Widgets Application

    在这里插入图片描述
    Step3:对project进行命名并将其保存在某一文件路径中(命名任意均可,但不能有中文,中文符号也不能有,项目路径保存任意,没有要求)
    在这里插入图片描述
    Step4:默认下一步即可
    在这里插入图片描述
    Step5:Base class选择为QWidget,Class name可以自己任意命名,这里我命名为Calcilator_UI,还有就是一定要勾选Generate from(生成界面所用)
    在这里插入图片描述
    Step6:选择Desktop Qt 5.13.2 MinGW 64-bit
    在这里插入图片描述
    Step7:默认下一步
    在这里插入图片描述

    界面布局

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    这里的布局只是示范,小伙伴们可以根据自己的审美观念来设计更好看的布局

    样式的添加

    Step1:添加myhelper.h和myhelper.cpp文件
    在这里插入图片描述
    在这里插入图片描述
    Class name定义为myhelper,Base class定义为QWidget
    在这里插入图片描述
    默认下一步,然后点击完成即myhelper创建成功

    Step2:添加相应代码
    myhelper.h文件如下:

    #ifndef MYHELPER_H
    #define MYHELPER_H
    
    #include <QWidget>
    #include <QtCore>
    #include <QtGui>
    #include <QDesktopWidget>
    #include <QApplication>
    
    class myhelper : public QWidget
    {
        Q_OBJECT
    public:
        explicit myhelper(QWidget *parent = nullptr);
        //设置为开机启动
        static void AutoRunWithSystem(bool IsAutoRun, QString AppName, QString AppPath)
        {
            QSettings *reg = new QSettings(
                "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                QSettings::NativeFormat);
    
            if (IsAutoRun) {
                reg->setValue(AppName, AppPath);
            } else {
                reg->setValue(AppName, "");
            }
        }
    
        //设置编码为UTF8
        static void SetUTF8Code()
        {
    #if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
            QTextCodec *codec = QTextCodec::codecForName("UTF-8");
            QTextCodec::setCodecForLocale(codec);
            QTextCodec::setCodecForCStrings(codec);
            QTextCodec::setCodecForTr(codec);
    #endif
        }
    
        //设置皮肤样式
        static void SetStyle(const QString &styleName)
        {
            QFile file(QString("://image/%1.css").arg(styleName));
            file.open(QFile::ReadOnly);
            QString qss = QLatin1String(file.readAll());
            qApp->setStyleSheet(qss);
            qApp->setPalette(QPalette(QColor("#F0F0F0")));
        }
    
        //加载中文字符
        static void SetChinese()
        {
            QTranslator *translator = new QTranslator(qApp);
            translator->load("://image/qt_zh_CN.qm");
            qApp->installTranslator(translator);
        }
    
        //判断是否是IP地址
        static bool IsIP(QString IP)
        {
            QRegExp RegExp("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");
            return RegExp.exactMatch(IP);
        }
    
    
    
        //延时
        static void Sleep(int sec)
        {
            QTime dieTime = QTime::currentTime().addMSecs(sec);
            while ( QTime::currentTime() < dieTime ) {
                QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
            }
        }
    
        //窗体居中显示
        static void FormInCenter(QWidget *frm)
        {
            int frmX = frm->width();
            int frmY = frm->height();
            QDesktopWidget w;
            int deskWidth = w.width();
            int deskHeight = w.height();
            QPoint movePoint(deskWidth / 2 - frmX / 2, deskHeight / 2 - frmY / 2);
            frm->move(movePoint);
        }
    
    signals:
    
    public slots:
    };
    
    #endif // MYHELPER_H
    
    

    myhelper.cpp文件如下:

    #include "myhelper.h"
    
    myhelper::myhelper(QWidget *parent) : QWidget(parent)
    {
    
    }
    

    Step3:添加资源

    在这里插入图片描述
    选择Qt中的Qt Resource File

    在这里插入图片描述
    在这里插入图片描述
    记住这里的名称一定要为rc,因为这是与程序里相对应的,若不命名为rc,则需对接下来的程序进行稍作修改

    接下来就是默认完成
    在这里插入图片描述
    然后添加前缀
    在这里插入图片描述
    前缀的名称一定要为’/’
    在这里插入图片描述
    在这里插入图片描述
    然后添加当前路径中image文件中所有的样式
    在这里插入图片描述

    在这里插入图片描述

    然后再编译一下,编译后结果如下所示
    在这里插入图片描述
    image文件下载

    Step4:添加icon_style.h和icon_style.cpp文件
    在添加之前先在Calculator.pro文件中添加QT += sql,然后编译一下
    在这里插入图片描述
    接着添加icon_style.h和icon_style.cpp文件
    在这里插入图片描述
    Class name定义为icon_style,Base class定义为QWidget
    在这里插入图片描述
    接下来就是默认完成
    在这里插入图片描述
    Step5:添加相应代码
    icon_style.h文件如下:

    #ifndef ICON_STYLE_H
    #define ICON_STYLE_H
    
    #include <QWidget>
    #include <QFont>
    #include <QFontDatabase>
    #include <QMutex>
    #include <QLabel>
    #include <QPushButton>
    #include <QApplication>
    
    class icon_style : public QWidget
    {
        Q_OBJECT
    public:
        explicit icon_style(QWidget *parent = nullptr);
        static icon_style* Instance()
        {
            static QMutex mutex;
            if (!_instance) {
                QMutexLocker locker(&mutex);
                if (!_instance) {
                    _instance = new icon_style;
                }
            }
            return _instance;
        }
    
        void SetIcon(QLabel* lab, QChar c, int size = 10);
        void SetIcon(QPushButton* btn, QChar c, int size = 10);
    
    signals:
    
    private:
        QFont iconFont;
        static icon_style* _instance;
    
    public slots:
    };
    
    #endif // ICON_STYLE_H
    
    

    icon_style.cpp文件如下:

    #include "icon_style.h"
    
    icon_style* icon_style::_instance = 0;
    icon_style::icon_style(QWidget *parent) : QWidget(parent)
    {
        int fontId = QFontDatabase::addApplicationFont(":/image/fontawesome-webfont.ttf");
        QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0);
        iconFont = QFont(fontName);
    }
    
    void icon_style::SetIcon(QLabel* lab, QChar c, int size)
    {
        iconFont.setPointSize(size);
        lab->setFont(iconFont);
        lab->setText(c);
    }
    
    void icon_style::SetIcon(QPushButton* btn, QChar c, int size)
    {
        iconFont.setPointSize(size);
        btn->setFont(iconFont);
        btn->setText(c);
    }
    
    

    与此同时calculator_ui.h文件更改为如下:

    #ifndef CALCULATOR_UI_H
    #define CALCULATOR_UI_H
    
    #include <QWidget>
    #include <QApplication>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Calculator_UI; }
    QT_END_NAMESPACE
    
    class Calculator_UI : public QWidget
    {
        Q_OBJECT
    
    public:
        Calculator_UI(QWidget *parent = nullptr);
        ~Calculator_UI();
        void InitStyle_Calculator();
    
    private:
        Ui::Calculator_UI *ui;
        QPoint mousePoint;
        bool mousePressed;
        bool max;
        QRect location;
    };
    #endif // CALCULATOR_UI_H
    
    

    calculator_ui.cpp文件更改为如下:

    #include "calculator_ui.h"
    #include "ui_calculator_ui.h"
    
    #include "myhelper.h"
    #include "icon_style.h"
    
    
    Calculator_UI::Calculator_UI(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Calculator_UI)
    {
        ui->setupUi(this);
    
        myhelper::FormInCenter(this);
        this->InitStyle_Calculator();
    
    }
    
    Calculator_UI::~Calculator_UI()
    {
        delete ui;
    }
    
    void Calculator_UI::InitStyle_Calculator()
    {
        //设置窗体标题栏隐藏
        this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
        location = this->geometry();
        max = false;
        mousePressed = false;
    
        //安装事件监听器,让标题栏识别鼠标双击
        ui->label_title->installEventFilter(this);
    
        icon_style::Instance()->SetIcon(ui->button_close, QChar(0xf00d), 10);
        icon_style::Instance()->SetIcon(ui->button_max, QChar(0xf096), 10);
        icon_style::Instance()->SetIcon(ui->button_min, QChar(0xf068), 10);
        icon_style::Instance()->SetIcon(ui->btnMenu, QChar(0xf0c9), 10);
        icon_style::Instance()->SetIcon(ui->lab_Ico, QChar(0xf015), 12);
    }
    
    

    main.cpp文件修改如下:

    #include "calculator_ui.h"
    
    #include "myhelper.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        myhelper::SetUTF8Code();
       myhelper::SetStyle("blue");//蓝色风格
    
       myhelper::SetChinese();
    
        Calculator_UI w;
        w.show();
        return a.exec();
    }
    
    

    编译运行后的效果如下图所示:

    在这里插入图片描述
    到这里按下界面上的按钮都不会有反应,接着添加缩小,放大以及关闭按钮功能
    首先在ui设计界面那里添加槽函数,即对于缩小,放大以及关闭按钮右击,然后点击转到槽,然后按下ok即可。这里以button_close为例:
    在这里插入图片描述
    在这里插入图片描述
    button_max和button_min类似

    calculator_ui.h文件添加后如下:

    #ifndef CALCULATOR_UI_H
    #define CALCULATOR_UI_H
    
    #include <QWidget>
    #include <QApplication>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Calculator_UI; }
    QT_END_NAMESPACE
    
    class Calculator_UI : public QWidget
    {
        Q_OBJECT
    
    public:
        Calculator_UI(QWidget *parent = nullptr);
        ~Calculator_UI();
        void InitStyle_Calculator();
    
    protected:
        bool eventFilter(QWidget *obj, QEvent *event);
        void mouseMoveEvent(QMouseEvent *e);
        void mousePressEvent(QMouseEvent *e);
        void mouseReleaseEvent(QMouseEvent *);
    
    private slots:
        void on_button_close_clicked();
    
        void on_button_max_clicked();
    
        void on_button_min_clicked();
    
    private:
        Ui::Calculator_UI *ui;
        QPoint mousePoint;
        bool mousePressed;
        bool max;
        QRect location;
    };
    #endif // CALCULATOR_UI_H
    
    

    calculator_ui.cpp文件添加后如下:

    #include "calculator_ui.h"
    #include "ui_calculator_ui.h"
    
    #include "myhelper.h"
    #include "icon_style.h"
    
    
    Calculator_UI::Calculator_UI(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Calculator_UI)
    {
        ui->setupUi(this);
    
        myhelper::FormInCenter(this);
        this->InitStyle_Calculator();
    
    }
    
    Calculator_UI::~Calculator_UI()
    {
        delete ui;
    }
    
    void Calculator_UI::InitStyle_Calculator()
    {
        //设置窗体标题栏隐藏
        this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
        location = this->geometry();
        max = false;
        mousePressed = false;
    
        //安装事件监听器,让标题栏识别鼠标双击
        ui->label_title->installEventFilter(this);
    
        icon_style::Instance()->SetIcon(ui->button_close, QChar(0xf00d), 10);
        icon_style::Instance()->SetIcon(ui->button_max, QChar(0xf096), 10);
        icon_style::Instance()->SetIcon(ui->button_min, QChar(0xf068), 10);
        icon_style::Instance()->SetIcon(ui->btnMenu, QChar(0xf0c9), 10);
        icon_style::Instance()->SetIcon(ui->lab_Ico, QChar(0xf015), 12);
    }
    
    bool Calculator_UI::eventFilter(QWidget*obj, QEvent *event)
    {
        if (event->type() == QEvent::MouseButtonDblClick) {
            this->on_button_max_clicked();
            return true;
        }
        return QObject::eventFilter(obj, event);
    }
    void Calculator_UI::mouseMoveEvent(QMouseEvent *e)
    {
        if (mousePressed && (e->buttons() && Qt::LeftButton) && !max)
        {
            this->move(e->globalPos() - mousePoint);
            e->accept();
        }
    }
    
    void Calculator_UI::mousePressEvent(QMouseEvent *e)
    {
        if (e->button() == Qt::LeftButton) {
            mousePressed = true;
            mousePoint = e->globalPos() - this->pos();
            e->accept();
        }
    }
    
    void Calculator_UI::mouseReleaseEvent(QMouseEvent *)
    {
        mousePressed = false;
    }
    
    
    void Calculator_UI::on_button_max_clicked()
    {
        if (max) {
            this->setGeometry(location);
            icon_style::Instance()->SetIcon(ui->button_max, QChar(0xf096), 10);
            ui->button_max->setToolTip("最大化");
        } else {
            location = this->geometry();
            this->setGeometry(qApp->desktop()->availableGeometry());
            icon_style::Instance()->SetIcon(ui->button_max, QChar(0xf079), 10);
            ui->button_max->setToolTip("还原");
        }
        max = !max;
    }
    
    void Calculator_UI::on_button_min_clicked()
    {
        this->showMinimized();
    }
    
    void Calculator_UI::on_button_close_clicked()
    {
        qApp->exit();
    }
    

    添加相应代码后,界面就可以缩小,关闭,移动以及放大,注意这里按下放大键后界面不会放大,因为在界面设计时,整体界面的最大长度,宽度以及最小长度和宽度都固定了,若想看到放大功能只需在界面设计中进行相应的调整并布局

    词法分析

    准备工作

    添加token.h和token.cpp文件,步骤与前面样式添加类似。
    右击Calculator_Design -> 点击Add New -> 选择C++里的C++ Class -> Class name 定为 token -> Base class 定为QWidget -> 点击下一步 -> 点击完成

    工程建立完成后,在正式编写代码时,先将Calculator_Design.pro中的c++ 11改为c++ 17标准,因为在后面的编程中需要用到c++17 新特性。
    在这里插入图片描述

    代码添加

    token.h
    #ifndef TOKEN_H
    #define TOKEN_H
    
    #include <QWidget>
    #include <string>
    #include <tuple>  //用来存储返回值
    #include <variant>
    #include <functional> //把lambda存储下来称为一个变量
    #include <optional>
    
    
    enum class TokenType
    {
        //数字
        Number,
        //符号,英文字母a-z,A-Z
        Symbo,
        //用来表示结束
        End,	//终止符号
        //用来表示错误
        Error,	//错误符号
        Plus = '+',
        Minus = '-',
        Mul = '*',
        Div = '/',
        Lp = '(',
        Rp = ')',
    
    };
    
    struct Token  //定义符号结构体
    {
        TokenType type;  //符号类型
        std::variant<double,std::string> value = 0.0;
    };
    
    
    //查找符号在符号表中的具体定义
    std::optional<std::variant<double, std::function<double(double)>>> getSymboValue(std::string symbo);
    
    
    //input = "1 + 2 * 3"
    //tokenize("1 + 2 * 3") -> 符号1 + 剩余的字符串"+ 2 * 3"
    //tokenize("+ 2 * 3") -> 运算符+ + 剩余的字符串"2 * 3"
    //tokenize("2 * 3") -> 数字2 + 剩余的字符串"* 3"
    //....
    //这里返回值是多个,可以用tuple
    std::tuple<Token, std::string> tokenize(std::string input);
    //输入为 std::string input
    //第一个返回值为Token,第二个返回值为剩下字符串std::string
    
    class token : public QWidget
    {
        Q_OBJECT
    public:
        explicit token(QWidget *parent = nullptr);
    
    signals:
    
    public slots:
    };
    
    #endif // TOKEN_H
    
    
    token.cpp
    #include "token.h"
    #include <math.h>
    #include <stdexcept>  //异常处理
    #include <unordered_map> //索引值可以为字符串
    #include <functional> //把lambda存储下来称为一个变量
    
    
    //符号表
    //索引值是string
    //返回类型为variant,有两种可能一种就是double,另一种是输入为double,返回为double的一个函数
    static std::unordered_map<std::string, std::variant<double, std::function<double(double)>>> SymboTable
    {
        {"PI",atan(1.0) * 4},
        {"e",exp(1.0)},
        {"sin",[](double val) {return sin(val); }},
        {"cos",[](double val) {return cos(val); }},
        {"asin",[](double val) {return asin(val); }},
        {"acos",[](double val) {return acos(val); }},
        {"tan",[](double val) {return tan(val); }},
        {"atan",[](double val) {return atan(val); }},
        {"sqrt",[](double val) {return sqrt(val); }},
        {"log", [](double val) {return log(val); }},
    };
    
    
    //解析符号
    static std::tuple<std::string, std::string> parseSymbo(std::string input)
    {
        std::string symbo;
        while (1)
        {
            //输入字符串到头了,退出死循环
            if (input.empty())
            {
                break;
            }
            //得到第一个字符
            char ch = input.front();
            if (isalpha(ch))
            {
                symbo.push_back(ch);
                input.erase(input.begin());
            }
            else
            {
                break;
            }
        }
        return { symbo,input };
    }
    
    //用static表示此函数只在该.cpp文件中有意义
    static std::tuple<double, std::string> parseNumber(std::string input)
    {
        std::string numstr;
        //表示第一次遇到小数点
        //避免1.5.5这种情况
        bool firstDot = true;
    
        while (1)
        {
            if (input.empty())
            {
                break;
            }
            char ch = input.front();
    
            if ((ch >= '0' && ch <= '9') || (ch == '.' && firstDot))
            {
                numstr.push_back(ch);
    
                input.erase(input.begin());
                if (ch == '.')
                {
                    firstDot = false;
                }
    
            }
            else
            {
                break;
            }
    
        }
        //stod用于将字符转化为数字
        return { std::stod(numstr) , input };
    
    }
    
    //查找符号在符号表中的具体定义
    std::optional<std::variant<double, std::function<double(double)>>> getSymboValue(std::string symbo)
    {
        if (auto iter = SymboTable.find(symbo); iter != SymboTable.end())
        {
            //返回它的具体取值
            return { iter->second };
        }
        return {};
    }
    
    
    std::tuple<Token, std::string> tokenize(std::string input)
    {
        Token tk;
        char ch;
        //第一件事情是去除掉开头的空格
        do
        {
            if (input.empty()) //输入为空
            {
                tk.type = TokenType::End;
                return { tk,"" };
            }
            else
            {
                //拿到input最开头的字符
                ch = input.front();//取最前面的字符
                //并且把这个字符从input的开头去掉
                input.erase(input.begin());
            }
    
        } while (ch == ' ');
        //第二件事情是根据第一个非空格的字符生产相应的token用于返回
        switch (ch)
        {
        case '+':
        case '-':
        case '*':
        case '/':
        case '(':
        case ')':
            tk.type = TokenType(ch);
            break;
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            tk.type = TokenType::Number;
            //把ch重新添加到input的开头
            //比如开头为1.0
            input.insert(input.begin(), ch);
            //把这个字符串中的数字变成真正的数值
            std::tie(tk.value, input) = parseNumber(input);
            break;
        default:
            //判断是否是a-z,A-Z的字符
            if (isalpha(ch))
            {
                tk.type = TokenType::Symbo;
                //把ch重新添加到input的开头
                input.insert(input.begin(), ch);
                //解析出这个symbo
                std::tie(tk.value, input) = parseSymbo(input);
            }
            else
            {
                //用异常来表示错误
                throw std::runtime_error("错误: 存在不合法的符号!\n");
            }
            break;
        }
        return { tk,input };
    }
    
    token::token(QWidget *parent) : QWidget(parent)
    {
    
    }
    
    

    语法分析

    准备工作

    添加parser.h和parser.cpp文件,步骤与前面样式添加类似。
    右击Calculator_Design -> 点击Add New -> 选择C++里的C++ Class -> Class name 定为 parser -> Base class 定为QWidget -> 点击下一步 -> 点击完成
    工程建立完成后,开始编写代码

    代码添加

    parser.h
    #ifndef PARSER_H
    #define PARSER_H
    
    #include <QWidget>
    #include <string>
    #include <tuple>
    
    //解析不是一次性的,而是逐个解析 所以返回还是用tuple来返回多个值
    std::tuple<double, std::string> parseExpress(std::string input);
    
    class parser : public QWidget
    {
        Q_OBJECT
    public:
        explicit parser(QWidget *parent = nullptr);
        bool is_contain_lp = false;
    
    signals:
    
    
    public slots:
    };
    
    #endif // PARSER_H
    
    
    parser.cpp
    #include "parser.h"
    #include "token.h"
    
    //解析不是一次性的,而是逐个解析 所以返回还是用tuple来返回多个值
    static std::tuple<double, std::string> parseFactor(std::string input)
    {
        double result;
        Token tk;
        //解析第一个token
        std::tie(tk, input) = tokenize(input);
    
        switch (tk.type)
        {
        case TokenType::Number:
            result = std::get<double>(tk.value);
            break;
    
        case TokenType::Symbo:
        {	//先搜索符号是否在符号表中有定义
            auto search = getSymboValue(std::get<std::string>(tk.value));
    
            if (search)
            {
                //有两种情况
                //情况1 symbo是常量,此时result等于symbo对应的常量具体数值
                if (std::holds_alternative<double>(search.value()))
                {
                    result = std::get<double>(search.value());
                }
                //情况2 symbo是函数,此时继续解析(E)并把解析出来的E作用于symbo对应的函数
                //函数计算出来的值赋给result
                else
                {
                    //得到函数本体
                    auto fun = std::get<std::function<double(double)>>(search.value());
                    //解析一个(
                    std::tie(tk, input) = tokenize(input);
                    if (tk.type != TokenType::Lp)
                    {
                        throw std::runtime_error("语法错误:表达式缺'('\n");
                    }
                    //解析表达式
                    double v;
                    std::tie(v, input) = parseExpress(input);
                    //解析)
                    std::tie(tk, input) = tokenize(input);
                    if (tk.type != TokenType::Rp)
                    {
                        throw std::runtime_error("语法错误:表达式缺')'!\n");
                    }
                    result = fun(v);
    
                }
            }
            //找不到符号抛出异常
            else
            {
                throw std::runtime_error("语法错误: 存在不合法的符号 "+ std::get<std::string>(tk.value)+"\n");
            }
    
            break;
        }
        case TokenType::Lp:
            //解析(E)里的E
            std::tie(result, input) = parseExpress(input);
            //再解析一个)
            std::tie(tk, input) = tokenize(input);
            //如果解析出来的不是)则说明输入的这个表达式有错
            if (tk.type != TokenType::Rp)
            {
                throw std::runtime_error("语法错误:表达式缺')'!\n");
            }
            break;
        default:
            //语法出错,应抛出异常
            throw std::runtime_error("语法错误: 表达式缺数字或者'('!\n");
            break;
        }
        return { result,input };
    }
    //解析不是一次性的,而是逐个解析 所以返回还是用tuple来返回多个值
    static std::tuple<double, std::string> parseTerm(std::string input)
    {
        double result;
        //翻译T -> FR中的F
        std::tie(result, input) = parseFactor(input);
    
        //翻译T -> FR中的R
        bool loop = true; //用此变量用于跳出循环
        while (loop)
        {
            Token op;
            std::string res;
            double term;
            //翻译R -> *TR | /TR | null 的第一个token,那就是 + 或者 - 或者是空
            std::tie(op, res) = tokenize(input);
    
            switch (op.type)
            {
            case TokenType::Mul:
                //解析*TR中的T
                std::tie(term, input) = parseFactor(res);
                //根据乘法的语义更新result的数值
                result *= term;
                break;
            case TokenType::Div:
                //解析/TR中的T
                std::tie(term, input) = parseFactor(res);
                //不可以除以0
                if (term == 0.0)
                {
                    throw std::runtime_error("错误: 除数不能为0!\n");
                }
                //根据除法的语义更新result的数值
                result /= term;
                break;
            default:
                //退出循环
                loop = false;
                break;
            }
        }
    
        return { result,input };
    }
    
    //解析不是一次性的,而是逐个解析 所以返回还是用tuple来返回多个值
    //E -> TR
    //R -> +TR | -TR | null
     std::tuple<double, std::string> parseExpress(std::string input)
    {
        double result;
        //翻译E -> TR
        std::tie(result, input) = parseTerm(input);
    
        //翻译E -> TR中的R
        bool loop = true; //用此变量用于跳出循环
        while (loop)
        {
            Token op;
            std::string res;
            double term;
            //翻译R -> +TR | -TR | null 的第一个token,那就是 + 或者 - 或者是空
            std::tie(op, res) = tokenize(input);
    
            switch (op.type)
            {
            case TokenType::Plus:
                //解析+TR中的T
                std::tie(term,input) = parseTerm(res);
                //根据加法的语义更新result的数值
                result += term;
                break;
            case TokenType::Minus:
                //解析-TR中的T
                std::tie(term, input) = parseTerm(res);
                //根据减法的语义更新result的数值
                result -= term;
                break;
            default:
                //退出循环
                loop = false;
                break;
            }
        }
    
        return { result,input };
    }
    parser::parser(QWidget *parent) : QWidget(parent)
    {
    
    }
    
    

    不带界面的测试

    main.cpp

    #include "calculator_ui.h"
    
    #include "myhelper.h"
    #include <QApplication>
    #include "parser.h"
    #include <stdio.h>
    #include <QDebug>
    
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        //std::string input = "1.23 + 2 * (1 + 2 / 5 - 4)";
        std::string input = "1.23 + 2 * (1 + 2 / 5 - 4)";
        //std::string input = "1+tan(PI/4)";
        //std::string input = "1+sin(PI/6)*sqrt(32*sin(PI/6))";
        //auto[result,res] = parseExpress(input);
        try
        {
            auto[result, res] = parseExpress(input);
            qDebug() << result;
        }
        catch (std::exception& e)
        {
            qDebug() << e.what();
        }
        myhelper::SetUTF8Code();
       myhelper::SetStyle("blue");//蓝色风格
    
       myhelper::SetChinese();
    
        Calculator_UI w;
        w.show();
        return a.exec();
    }
    
    

    测试结果如下:在这里插入图片描述

    实现界面计算功能

    准备工作

    双击calculator_ui.ui -> 右击每个按钮-> 点击转到槽 -> 点击ok

    代码添加

    calculator_ui.h
    #ifndef CALCULATOR_UI_H
    #define CALCULATOR_UI_H
    
    #include <QWidget>
    #include <QApplication>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Calculator_UI; }
    QT_END_NAMESPACE
    
    class Calculator_UI : public QWidget
    {
        Q_OBJECT
    
    public:
        Calculator_UI(QWidget *parent = nullptr);
        ~Calculator_UI();
        void InitStyle_Calculator();
    
    protected:
        bool eventFilter(QWidget *obj, QEvent *event);
        void mouseMoveEvent(QMouseEvent *e);
        void mousePressEvent(QMouseEvent *e);
        void mouseReleaseEvent(QMouseEvent *);
    
    private slots:
        void on_button_close_clicked();
    
        void on_button_max_clicked();
    
        void on_button_min_clicked();
    
        void on_button_0_clicked();
    
        void on_button_1_clicked();
    
        void on_button_2_clicked();
    
        void on_button_3_clicked();
    
        void on_button_4_clicked();
    
        void on_button_5_clicked();
    
        void on_button_6_clicked();
    
        void on_button_7_clicked();
    
        void on_button_8_clicked();
    
        void on_button_9_clicked();
    
        void on_button_dot_clicked();
    
        void on_button_clear_clicked();
    
        void on_button_back_clicked();
    
        void on_button_Plus_clicked();
    
        void on_button_Minus_clicked();
    
        void on_button_Mul_clicked();
    
        void on_button_Div_clicked();
    
        void on_button_Lp_clicked();
    
        void on_button_Rp_clicked();
    
        void on_button_euqal_clicked();
    
        void on_button_sin_clicked();
    
        void on_button_asin_clicked();
    
        void on_button_cos_clicked();
    
        void on_button_acos_clicked();
    
        void on_button_tan_clicked();
    
        void on_button_atan_clicked();
    
        void on_button_sqrt_clicked();
    
        void on_button_log_clicked();
    
        void on_button_PI_clicked();
    
        void on_button_e_clicked();
    
    private:
        Ui::Calculator_UI *ui;
        QPoint mousePoint;
        bool mousePressed;
        bool max;
        QRect location;
    
        //初始化输出框显示0
        QString my_Display = "0";
    
        //判断是否第一次输入,若是则为true
        bool is_FirstInput = true;
    
        //判断是否出错,若出错则为true,否则为false
        bool is_Error = false;
    
        //判断是否有运算符,若有则为true,若没有则为false
        bool is_Sym = false;
    
        //判断"("左边是数字还是+-*/(,若是数字则为true,否则为false
        bool lp_left_is_num = false;
    };
    #endif // CALCULATOR_UI_H
    
    calculator_ui.cpp
    #include "calculator_ui.h"
    #include "ui_calculator_ui.h"
    
    #include "myhelper.h"
    #include "icon_style.h"
    #include <string>
    #include <stdexcept>
    #include "parser.h"
    
    #include <QVariantList>
    //设置文本框的显示方式
    #include <QCompleter>
    #include <QStringList>
    
    #include <QPushButton>
    #include <QLineEdit>
    
    //QT正则表达式引擎
    #include <QRegExp>
    
    
    Calculator_UI::Calculator_UI(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Calculator_UI)
    {
        ui->setupUi(this);
    
        myhelper::FormInCenter(this);
        this->InitStyle_Calculator();
        ui->lineEdit->setText(my_Display);
    
    }
    
    Calculator_UI::~Calculator_UI()
    {
        delete ui;
    }
    
    void Calculator_UI::InitStyle_Calculator()
    {
        //设置窗体标题栏隐藏
        this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
        location = this->geometry();
        max = false;
        mousePressed = false;
    
        //安装事件监听器,让标题栏识别鼠标双击
        ui->label_title->installEventFilter(this);
    
        icon_style::Instance()->SetIcon(ui->button_close, QChar(0xf00d), 10);
        icon_style::Instance()->SetIcon(ui->button_max, QChar(0xf096), 10);
        icon_style::Instance()->SetIcon(ui->button_min, QChar(0xf068), 10);
        icon_style::Instance()->SetIcon(ui->btnMenu, QChar(0xf0c9), 10);
        icon_style::Instance()->SetIcon(ui->lab_Ico, QChar(0xf015), 12);
    }
    
    bool Calculator_UI::eventFilter(QWidget*obj, QEvent *event)
    {
        if (event->type() == QEvent::MouseButtonDblClick) {
            this->on_button_max_clicked();
            return true;
        }
        return QObject::eventFilter(obj, event);
    }
    void Calculator_UI::mouseMoveEvent(QMouseEvent *e)
    {
        if (mousePressed && (e->buttons() && Qt::LeftButton) && !max)
        {
            this->move(e->globalPos() - mousePoint);
            e->accept();
        }
    }
    
    void Calculator_UI::mousePressEvent(QMouseEvent *e)
    {
        if (e->button() == Qt::LeftButton) {
            mousePressed = true;
            mousePoint = e->globalPos() - this->pos();
            e->accept();
        }
    }
    
    void Calculator_UI::mouseReleaseEvent(QMouseEvent *)
    {
        mousePressed = false;
    }
    
    
    void Calculator_UI::on_button_max_clicked()
    {
        if (max) {
            this->setGeometry(location);
            icon_style::Instance()->SetIcon(ui->button_max, QChar(0xf096), 10);
            ui->button_max->setToolTip("最大化");
        } else {
            location = this->geometry();
            this->setGeometry(qApp->desktop()->availableGeometry());
            icon_style::Instance()->SetIcon(ui->button_max, QChar(0xf079), 10);
            ui->button_max->setToolTip("还原");
        }
        max = !max;
    }
    
    void Calculator_UI::on_button_min_clicked()
    {
        this->showMinimized();
    }
    
    void Calculator_UI::on_button_close_clicked()
    {
        qApp->exit();
    }
    
    
    
    void Calculator_UI::on_button_0_clicked()
    {
        //将文本框的内容赋给my_Display
        my_Display = ui->lineEdit->text();
        //获取按下按钮的信息
        QString text = ui->button_0->text();
        if(my_Display!="0")   //不是第一个0(不是只有一个0)
        {
            //找到最后一个+-*/()的位置
            auto index = my_Display.lastIndexOf(QRegExp("[+-*/()]"));
            if(index!=-1)
            {
                //找到最后一个+-*/()后的字符串
                auto res = my_Display.right(my_Display.length()-index-1);
                if(res != "0")
                {
                    my_Display += "0";
                    ui->lineEdit->setText(my_Display);
    
                }
            }
            else
            {
                my_Display += "0";
                ui->lineEdit->setText(my_Display);
            }
        }
    
    
        bool is_Sym = my_Display.contains(QRegExp("[+-*/]"));
        //用于显示最初0.0000.....number
        bool is_Number = my_Display.contains(QRegExp("[123456789]"));
        if(!is_Sym && is_Number)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_1_clicked()
    {
        //这里将文本框的内容赋给my_Display是为了兼顾键盘输入
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_1->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_2_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_2->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    
    void Calculator_UI::on_button_3_clicked()
    {
        my_Display = ui->lineEdit->text();
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_3->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_4_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_4->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_5_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_5->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_6_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_6->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_7_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_7->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_8_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_8->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_9_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_9->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_dot_clicked()
    {
        my_Display = ui->lineEdit->text();
        //先找到文本最后一个'.'
        auto index = my_Display.lastIndexOf('.');
        if(index == -1)  //前面不存在小数点
        {
            my_Display += '.';
            ui->lineEdit->setText(my_Display);
            is_Sym = true;
            is_FirstInput = false;
            is_Error = false;
        }
        else
        {
            //把最后一个小数点之后的字符串取出来
            auto res = my_Display.right(my_Display.length()- index - 1);
            //判断这个res中是否存在运算符() + - * / (正则表达式)
            //rbegin的r的意思是reverse
            if(res.contains(QRegExp("[()+-*/]")) && res.rbegin()->isNumber())
            {
                my_Display += '.';
                ui->lineEdit->setText(my_Display);
            }
        }
    
    }
    
    //清空
    void Calculator_UI::on_button_clear_clicked()
    {
        my_Display = ui->lineEdit->text();
        my_Display = "0";
        is_FirstInput = true;
        ui->lineEdit->setText(my_Display);
    }
    
    //退格
    void Calculator_UI::on_button_back_clicked()
    {
        my_Display = ui->lineEdit->text();
        if(my_Display != "")
        {
            my_Display.remove(my_Display.length()-1,1);
            ui->lineEdit->setText(my_Display);
    
        }
        if(my_Display == "")
        {
            my_Display = "0";
            ui->lineEdit->setText(my_Display);
            is_FirstInput = true;
        }
    }
    
    void Calculator_UI::on_button_Plus_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_Plus->text();
    
        //在现有文本基础上添加新按钮
        my_Display += text;
        //为了让计算后可以接着计算
        is_Sym = my_Display.contains(QRegExp("[+-*/]"));
    
        //设置回去
        ui->lineEdit->setText(my_Display);
    
    }
    
    void Calculator_UI::on_button_Minus_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_Minus->text();
    
        //在现有文本基础上添加新按钮
        my_Display += text;
    
        is_Sym = my_Display.contains(QRegExp("[+-*/]"));
        //设置回去
        ui->lineEdit->setText(my_Display);
    }
    
    void Calculator_UI::on_button_Mul_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_Mul->text();
    
        //在现有文本基础上添加新按钮
        my_Display += text;
    
        is_Sym = my_Display.contains(QRegExp("[+-*/]"));
        //设置回去
        ui->lineEdit->setText(my_Display);
    }
    
    void Calculator_UI::on_button_Div_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_Div->text();
    
        //在现有文本基础上添加新按钮
        my_Display += text;
    
        is_Sym = my_Display.contains(QRegExp("[+-*/]"));
        //设置回去
        ui->lineEdit->setText(my_Display);
    }
    
    void Calculator_UI::on_button_Lp_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_Lp->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮的值
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
        //找到最后一个"("的位置
        auto index = my_Display.lastIndexOf("(");
    
        //找到最后一个"("前面一个字符和它本身
        auto res = my_Display.right(my_Display.length()-index+1);
        res = res.left(res.length()-1);
        bool lp_left_is_sym = res.contains(QRegExp("[+-*/(gnst]")); 
       //g,n,s,t分别表示log,tan,atan...最后一个字符
        if(!lp_left_is_sym && index!=0)
        {
            lp_left_is_num = true;
        }
    }
    
    void Calculator_UI::on_button_Rp_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_Rp->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮的值
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    
    }
    
    //计算
    void Calculator_UI::on_button_euqal_clicked()
    {
        my_Display = ui->lineEdit->text();
        //统计'('的个数
        int count_lp=0;
        //统计')'的个数
        int count_rp=0;
        for(int i=0;i<my_Display.length();i++)
        {
            if(my_Display[i] == '(')
            {
                count_lp++;
            }
            if(my_Display[i] == ')')
            {
                count_rp++;
            }
    
        }
        try
        {
            auto[result, res] = parseExpress(my_Display.toLatin1().data());
            my_Display = QString::number(result);
            is_Sym = false;
            //设置回去
            ui->lineEdit->setText(my_Display);
            if(lp_left_is_num == true)
            {
                is_Error = true;
                lp_left_is_num = false;
                throw std::runtime_error("错误: 符号'('左边缺失运算符!\n");
            }
            if(count_lp != count_rp)
            {
                throw std::runtime_error("错误: 符号 '(' 与 ')' 个数不匹配!\n");
            }
        }
        catch (std::exception& e)
        {
            my_Display = e.what();
            is_Error = true;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    
    
    void Calculator_UI::on_button_sin_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_sin->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_asin_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_asin->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_cos_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_cos->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_acos_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_acos->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_tan_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_tan->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_atan_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_atan->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_sqrt_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_sqrt->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_log_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_log->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_PI_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_PI->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    void Calculator_UI::on_button_e_clicked()
    {
        my_Display = ui->lineEdit->text();
        //获取文本信息
        QString text = ui->button_e->text();
    
        if(is_FirstInput || is_Error || !is_Sym)
        {
            my_Display = text;
            ui->lineEdit->setText(my_Display);
            is_FirstInput = false;
            is_Error = false;
            is_Sym = true;
        }
        else
        {
            //在现有文本基础上添加新按钮
            my_Display += text;
            //设置回去
            ui->lineEdit->setText(my_Display);
        }
    }
    
    

    带界面的测试

    正确计算测试

    测试1

    在这里插入图片描述
    在这里插入图片描述

    测试2

    在这里插入图片描述
    在这里插入图片描述

    测试3

    在这里插入图片描述
    在这里插入图片描述

    错误计算测试

    测试1

    在这里插入图片描述
    在这里插入图片描述

    测试2

    在这里插入图片描述
    在这里插入图片描述

    测试3

    在这里插入图片描述
    在这里插入图片描述

    测试4

    在这里插入图片描述

    在这里插入图片描述

    完整工程下载

    简易计算器

    展开全文
  • 使用Java写公式计算器

    万次阅读 热门讨论 2018-12-15 16:20:07
    一位好友需要软件里面内置一个小插件,可以根据用户输入的简单公式引导用户进行输入和计算,所以简单地写了一个原理实现。主要用到Java字符串处理和数据结构栈思想,难度不大但要非常细心。 原理如下: 1、...

    我的一位好友需要软件里面内置一个小插件,可以根据用户输入的简单公式引导用户进行输入和计算,所以简单地写了一个原理实现。主要用到Java字符串处理和数据结构的栈思想,难度不大但要非常细心。

    原理如下:

    1、对公式以等号为分隔符进行左右分割,然后取得公式右边字符串

    2、对公式右边字符串进行运算符(+、-、*、/、(、))和常数的去除,然后分割出变量名

    3、请求用户输入各变量的值,用用户输入值取代字符串的对应变量,使得公式变成纯数字和纯运算符构成的字符串。

    4、最复杂的一环:寻找第一个右括号(想到于找到栈顶),然后倒过来找左括号(如公式格式正确则必然同时是最后一个左括号),左括号和右括号作为一个整体提取作为子字符串。子字符串里面先找乘法和除法的子子字符串进行计算,再找加法和除法的子子字符串进行计算(按运算符查找,并找到符号两边的数值),然后运算完之后替换回去作为新的子字符串,直到子字符串没有运算符则结束。

    5、子字符串为括号内部运算的最终结果,用该结果替换整个子字符串,调到第1步开始重复。直到公式没有一个运算符停止

     

    实现代码:

    package com.test.calc;
    
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    import java.util.Scanner;
    import java.util.Stack;
    import java.util.function.Consumer;
    
    /**公式计算器**/
    public class EquationCalculator {
    
    	/** 变量集合 **/
    	private static List<String> varList = new LinkedList<>();
    	/** 变量和值的key-value **/
    	private static Map<String, Float> varListWithValue = new HashMap<>();
    
    	public static void main(String[] args) {
    		Scanner scanner = new Scanner(System.in);
    		System.out.println("请输入你需要计算的公式:");
    		String formula = scanner.nextLine().replaceAll(" ", "");
    		//String formula = "f=k * (((m1 + m2) * (40 * x + 60 * y)) + 100) * m2 / (G1 + G2)".replaceAll(" ", ""); fortest
    		String equalationLeft = formula.split("=")[0];
    		String equalationRight = formula.split("=")[1];
    		/** 获取变量表: **/
    		getVarList(equalationRight);
    		/** 给变量赋值 **/
    		assignmentVarList(varList);
    		/** 代回公式进行替换 **/
    		String newFormula = replaceEquation(formula);
    		/** 进行计算 **/
    		System.out.println();
    		float result = calc(newFormula);
    		System.out.println("最终结果:" + equalationLeft + "=" + result);
    	}
    
    	/** 进行计算 **/
    	private static float calc(String newFormula) {
    		boolean stillHaveCalcSymbol = false;
    		do{
    			//System.out.println("before:" + newFormula);
    			/** 寻找最后一个左括号里面到第一个右括号里面1的内容 **/
    			char formulaArray[] = newFormula.toCharArray();
    			for (int i = 0; i < formulaArray.length; i++) {
    				if (formulaArray[i] == '+' || formulaArray[i] == '-'
    						|| formulaArray[i] == '*' || formulaArray[i] == '/'
    						|| formulaArray[i] == '(' || formulaArray[i] == ')') {
    					stillHaveCalcSymbol = true;
    				} else {
    					stillHaveCalcSymbol = false;
    				}
    			}
    			if (stillHaveCalcSymbol) {
    				String resultFormula = "";
    				//找最内层的括号里面的内容出来(含括号)
    				for (int i = 0; i < formulaArray.length; i++) {
    					if (formulaArray[i] == ')') {
    						int begin = 0;
    						for (int j = i; j >= 0; j--) {
    							if (formulaArray[j] == '(') {
    								begin = j;
    								break;
    							}
    						}
    						String calcString = newFormula.substring(begin, i + 1);
    						resultFormula = newFormula.replace(calcString, calcProc(calcString) + "");
    						//System.out.println(calcString);
    						break;
    					}
    				}
    				newFormula = resultFormula;
    			}
    		} while(stillHaveCalcSymbol);
    		//最后得到普通的顺序无括号公式:
    		System.out.println(newFormula);
    		//最后一次计算:
    		float result = calcProc("(" + newFormula.split("=")[1] + ")"); 
    		return result;
    	}
    
    	/**详细计算过程**/
    	private static float calcProc(String calcString) {
    //		if(calcString.contains("=")){
    //			calcString = calcString.split("=")[1];
    //		}
    		//calcString = calcString.replace("(", "");
    		//calcString = calcString.replace(")", "");
    	
    		String calcSymbol[] = {"\\*", "\\/", "\\+", "\\-"};
    		char calcSymbolChar[] = {'*', '/', '+', '-'};
    		boolean haveSymbol = true;
    		float result = 0f;
    		while(haveSymbol){
    			System.out.println("calcStr:" + calcString);
    			char calcCharArr[] = calcString.toCharArray();
    			result = 0f;
    			for (int i = 0; i < calcSymbol.length; i++) {
    				boolean alreadyFind = false;
    				for(int j = 0; j < calcCharArr.length; j++){
    					if(calcCharArr[j] == calcSymbolChar[i]){
    						//System.out.println("找到了" + calcSymbolChar[i]);
    						//以符号为中心,以左右两边的其他符号为边界找到两边的数
    						float num1 = 0f;
    						float num2 = 0f;
    						int bottom = 0;
    						for(int k = j - 1; k >= 0 && (calcCharArr[k] >= '0' && calcCharArr[k] <= '9' || calcCharArr[k] == '.') ; k--){
    							//System.out.println(calcCharArr[k] + "");
    							bottom = k;
    						}
    						//System.out.println("[j, bottom]:" + String.format("[%d, %d]", j, bottom));
    						num1 = Float.valueOf(calcString.substring(bottom, j));
    						System.out.println("num1:" + num1);
    						int top = 0;
    						for(int k = j + 1; k < calcString.length() && (calcCharArr[k] >= '0' && calcCharArr[k] <= '9' || calcCharArr[k] == '.'); k++){
    							top = k;
    						}
    						num2 = Float.valueOf(calcString.substring(j + 1, top + 1));
    						System.out.println("num2:" + num2);
    						switch(calcSymbolChar[i]){
    							case '*':
    								result = num1 * num2;
    								break;
    							case '/':
    								result = num1 / num2;
    								break;
    							case '+':
    								result = num1 + num2;
    								break;
    							case '-':
    								result = num1 - num2;
    								break;
    						}
    						//System.out.println("bottom to top:" + calcString.substring(bottom + 1, top + 1)); 
    						calcString = calcString.replace(calcString.substring(bottom, top + 1), String.format("%.5f", result));
    						//System.out.println("end_calcStr:" + calcString);
    						alreadyFind = true;
    						break;
    					}
    				}
    				if(alreadyFind) break;
    			}
    			haveSymbol = false;
    			if(calcString.contains("*") || calcString.contains("/") || calcString.contains("+") || calcString.contains("-")){
    				haveSymbol = true;
    				//System.out.println("找到");
    			} else {
    				//System.out.println("找不到");
    			}
    		}
    		//System.out.println("result:" + result);
    		return result;
    	}
    
    	/** 代回公式进行替换 **/
    	private static String replaceEquation(String formula) {
    		String newFormula = new String(formula);
    		for (String key : varList) {
    			newFormula = newFormula.replaceAll(key, varListWithValue.get(key)
    					+ "");
    		}
    		System.out.println(newFormula);
    		return newFormula;
    	}
    
    	/**
    	 * 给变量赋值
    	 * 
    	 * @param varList
    	 *            变量列表
    	 **/
    	private static void assignmentVarList(List<String> varList) {
    		System.out.println("请输入各变量的对应值");
    		Scanner scanner = new Scanner(System.in);
    		for (String key : varList) {
    			System.out.print(key + "'s value is:");
    			varListWithValue.put(key, scanner.nextFloat());
    		}
    		/*for (String key : varList) {
    			System.out.println("key:" + key + ", value:"
    					+ varListWithValue.get(key));
    		}*/
    	}
    
    	/**
    	 * 获取变量表
    	 * 
    	 * @param equalationRight
    	 *            输入等式的右边
    	 **/
    	private static void getVarList(String equalationRight) {
    		System.out.println("等式右边:" + equalationRight);
    		char[] formulaCharArr;
    		formulaCharArr = equalationRight.toCharArray();
    		//清理所有运算符
    		for (int i = 0; i < formulaCharArr.length; i++) {
    			if (formulaCharArr[i] == '+' || formulaCharArr[i] == '-'
    					|| formulaCharArr[i] == '*' || formulaCharArr[i] == '/'
    					|| formulaCharArr[i] == '(' || formulaCharArr[i] == ')') {
    				formulaCharArr[i] = ' ';
    			}
    		}
    		/*String temp = "";
    		for (int i = 0; i < formulaCharArr.length; i++) {
    			if (formulaCharArr[i] == ' ') {
    				String content = temp.trim();
    				if (content.length() > 0) {
    					boolean okGo = true;
    					if(content.charAt(0) >= '0' && content.charAt(0) <= '9'){
    						okGo = false;
    					}
    					if (okGo) {
    						varList.add(content);
    					}
    				}
    				temp = "";
    			} else {
    				temp += formulaCharArr[i];
    			}
    		}*/
    		String pa[] = new String(formulaCharArr).split(" ");
    		for(String temp : pa){
    			if(temp != null && temp != "" && !temp.isEmpty()){
    				boolean okGo = true;
    				if(temp.charAt(0) >= '0' && temp.charAt(0) <= '9'){
    					okGo = false;
    				}
    				if (okGo) {
    					varList.add(temp);
    				}
    			}
    		}
    		System.out.println("变量列表:");
    		for (int h = 0; h < varList.size(); h++) {
    			String var = varList.get(h);
    			System.out.println(var);
    		}
    	}
    
    }
    

     

    测试1:

    请输入你需要计算的公式:
    j=b*y+a
    等式右边:b*y+a
    变量列表:
    b
    y
    a
    请输入各变量的对应值
    b's value is:55
    y's value is:66
    a's value is:77
    j=55.0*66.0+77.0

    j=55.0*66.0+77.0
    calcStr:(55.0*66.0+77.0)
    num1:55.0
    num2:66.0
    calcStr:(3630.00000+77.0)
    num1:3630.0
    num2:77.0
    最终结果:j=3707.0

     

     

    测试2:

    请输入你需要计算的公式:
    f=k * (((m1 + m2) * (40 * x + 60 * y)) + 100) * m2 / (G1 + G2) + (G3 * G4)
    等式右边:k*(((m1+m2)*(40*x+60*y))+100)*m2/(G1+G2)+(G3*G4)
    变量列表:
    k
    m1
    m2
    x
    y
    m2
    G1
    G2
    G3
    G4
    请输入各变量的对应值
    k's value is:1.1
    m1's value is:2.232
    m2's value is:3.333
    x's value is:4.567
    y's value is:31.44
    m2's value is:54.22
    G1's value is:5454
    G2's value is:111
    G3's value is:1112
    G4's value is:3333
    f=1.1*(((2.232+54.22)*(40*4.567+60*31.44))+100)*54.22/(5454.0+111.0)+(1112.0*3333.0)

    calcStr:(2.232+54.22)
    num1:2.232
    num2:54.22
    calcStr:(40*4.567+60*31.44)
    num1:40.0
    num2:4.567
    calcStr:(182.67999+60*31.44)
    num1:60.0
    num2:31.44
    calcStr:(182.67999+1886.40002)
    num1:182.68
    num2:1886.4
    calcStr:(56.452*2069.08)
    num1:56.452
    num2:2069.08
    calcStr:(116803.71+100)
    num1:116803.71
    num2:100.0
    calcStr:(5454.0+111.0)
    num1:5454.0
    num2:111.0
    calcStr:(1112.0*3333.0)
    num1:1112.0
    num2:3333.0
    f=1.1*116903.71*54.22/5565.0+3706296.0
    calcStr:(1.1*116903.71*54.22/5565.0+3706296.0)
    num1:1.1
    num2:116903.71
    calcStr:(128594.08594*54.22/5565.0+3706296.0)
    num1:128594.086
    num2:54.22
    calcStr:(6972371.50000/5565.0+3706296.0)
    num1:6972371.5
    num2:5565.0
    calcStr:(1252.89697+3706296.0)
    num1:1252.897
    num2:3706296.0
    最终结果:f=3707549.0
     

     

    展开全文
  • 易算数学公式计算器(易算器)是一款非常简单好用的公式计算器,您可以使 用并保存带变量的公式,在运行时只需要在变量列表中填入数据,就可以生 成结果列表,相信使用它可以减少您许多重复工作。 1 可以计算一般代数...
  • 栅格计算器(Raster Calculator) 是一种空间分析函数工具,可以输入地图代数表达式,使用运算符和函数来做数学计算,建立选择查询,或键入地图代数语法。只有熟练运用并记忆一些常用的公式,才能很好运用栅格...

    栅格计算器(Raster Calculator) 是一种空间分析函数工具,可以输入地图代数表达式,使用运算符和函数来做数学计算,建立选择查询,或键入地图代数语法。只有熟练的运用并记忆一些常用的公式,才能很好的运用栅格计算器。本文将常见的及一些容易出错的公式予以总结,方便学习工作是参考。网上关于本文的侵权版本特别多,请大家注意观察(文章发布的时间),不要被误导,以免影响大家的学习。

    扩展阅读:

    【ArcGIS风暴】ArcGIS10.6栅格计算器(Raster Calculator)用法详解

    【ArcGIS风暴】栅格计算器(Raster Calculator)运算出现错误问题及解决方案汇总

    ArcGIS10.2版本的山歌计算器面板如下所示: 

    上图为ArcGIS10.2中的栅格计算器工具,别以为看看着不起眼,但是功能强大的超乎每个GISer的想象,然而又有多少人能真正的理解并熟练的运用它呢?

    现在将一些常用的栅格计算函数举例归纳如下,用的时候可以参考:

    1、将特定值(-9999)赋值为0

        Con("raster"==-9999,0,"raster")

    2、将某一范围内(如小于0)赋值为0

        Con("raster" <0,0,"raster")

    3、将特定的栅格值(如1)赋值为空值

        setnull("raster"==1,"raster")

    4、给空值赋予特定的值(如0)

        CON(ISNULL("raster"),0,"raster")

    5、平方和开方

       (1)Power(raster,2),Power(raster,0.5)

       (2)Squre(),SquareRoot()

    6、提取栅格数据中特定值

       (1)Pick("raster",[1,2,3,......])

       (2)Slope>15,提取Slope大于15的格子,赋值为1,其余为0

       (3)Con("Slope">5,"Slope"),提取Slope大于5的格子,值不变

       (4)工具箱中Math下面的greater工具,结果为1和0

    7、将影像中的多个值赋予无效值

        SetNull(("raster == -32768)|("raster" == -10000),"raster")

    刘一哥GIS:专注测绘地理信息教育,探索地理奥秘,分享GIS价值!

    展开全文
  • 易算数学公式计算器介绍

    千次阅读 2010-10-25 20:55:00
    这是我用过最好用的公式计算器了。     1 可以计算一般代数式,比如“1 + cos(2)”。    2 可在表达式中使用变量,包括中文变量名,比如“电压=电阻*电流”。在  求值时,软件自动提示输入变量值并...
  • 考虑到公司业务有很多需要用到公式计算,决定封装一个类可以实现类似于计算器输入公式计算出结果效果。 思路 社保,公积金计算公式中有判断逻辑,如果工资多少则缴纳税百分比是多少,所以需要实现判断...
  • 用VC++开发类似WORD一个文字编辑软件,唯一不同是,在文本编辑器中输入一些系统定义关键字可以亮显,在文本中输入公式时,遇到等号时编辑器自动会得到计算结果。
  •  账龄在1-2年和2-3年金额,可以用min函数进行获取: 账龄在1-2年金额可以输入公式"=min(审定数-1年以下,上年审定数账龄在1年以内金额)" 以此类推。 账龄在3年以上,可以从平衡关系中直接倒挤出来。 ...
  • 计算器支持加减乘除开根号(其他功能可以自由扩展)。 利用状态机设计,可以根据设计要求,自由剪裁代码,只要在原始模板中,加入需要计算的公式,即可。
  • 用Python实现复杂的计算器可以按照“()”、乘除、加减的优先级进行混合运算。主旨是对正则表达式进行学习。 设计思路:  1.在计算式中搜索最后一个“(”,再搜索和它匹配的“)”,截取两个括号间的表达式...
  • 实现+ - * / ^ 混合运算科学计算器 计算页面可以收缩展开 可以查看历史计算过程 可以展开画图面板 自选颜色线型 输入公式画函数图象 还有待改进 不足之处请大神指点
  • 科学计算器 计算器

    热门讨论 2008-09-11 23:08:01
    外增加了一个“单步求解”的选项,可以一步一步显示出公式的计算过程。支持各种三角函数 ,运算的结果可选择弧度或角度值,这取决于计算器的角度|弧度按钮选择。打开表达式计算 的功能步骤是:鼠标右键单击液晶...
  • 很方便表达式计算器可以直接输入公式计算,自己扩容函数也很方便。
  • BMI_Calculator- BMICalculator.py是... 如果选择第二个选项(千克/米),则计算器会将这些单位转换为磅/英寸,这将产生基本相同结果,因为所有磅/英寸公式都使用了磅/英寸公式计算器会告诉您基于BMI健康状况。
  • MFC做钢材价格计算器。...每个页面可以根据公式参数不同而不同,每个页面要标有相应参数并紧跟着后面要有输入参数地方,如计算圆管话,页面上有显示管径mm后面可以输入参数。最后是提交按钮,显示结果。
  • 另外增加了一个“单步求解”的选项,可以一步一步显示出公式的计算过程。支持各种三角函数,运算的结果可选择弧度或角度值,这取决于计算器的角度|弧度按钮选择。打开表达式计算的功能步骤是:鼠标右键单击液晶屏幕...
  • 收藏夹可以收录您喜欢或常用的计算器,以便您需要时可以立即进行必要的计算!而且 支持多达4个线程一个浮动菜单,还能够将其他应用程序直接连接到 计算器。 主力功能: 拥有245个菜单条目,总共超过1000+个公式; ...
  • 手机计算器

    2012-11-01 16:03:07
    基于Android手机计算器程序,可以进行基本加减乘除运算,运算过程中可与把输入的计算公式保存在数据库中,下一次可以直接调用这个公式进行运算而不用在输入
  • JavaScript计算器

    2019-09-22 01:06:27
    JavaScript计算器 ... JavaScript计算器可以直接输入公式,然后按“计算”按钮,即可算出结果,学习JS运算一个例子。 <html><head><meta http-equiv="content-type" co...
  • 直接模式(输入公式,获取响应) 表格检视 这是我希望在不久将来实现目标: 更好错误报告 连贯UI 表“进入模式”和“跳转到”设置。 设置(禁用轴线,点而不是线,DEG或RAD等) 已知问题 一些问题是...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 147
精华内容 58
关键字:

可以输入公式的计算器