java加减乘除运算顺序_java 实现加减乘除混合运算

初衷:解决小学一年级到四年级 基本加减乘除混合运算

基本思路:

表达式:100+3+2-200+(10000/5+(100/2))

此类表达式我们称之为中缀表达式(运算符在数字的中间),如果我们稍加转换,转化为

100, 3, +, 2, +, 200, -, 10000, 5, /, 100, 2, /, +, +  转化后的表达式我们称之为后缀表达式(运算符在数字的后面),先不考虑该表达式是怎么来的,后面我们将详细介绍由中缀表达式转化为后缀表达式的实现过程;我们借助栈的数据结构(后进先出)来辅助我们解决这个问题,拿到转化后的结果 我们先创建一个空栈,从左往右开始运算,具体的运算逻辑为:

1.遇到数字则入栈

2.遇到运算符号 则将栈顶两元素出栈

3.根据运算符号进行运算并将运算结果入栈

4.表达式结束 则将栈顶元素 取出

我们先靠手来计算一下结果为1955;现在我们用这个规律来进行分析,

第一步:数字100先入栈;

26a90d6d2c0f5c5f62464c7ba3cb785d.png

第二步:数字3入栈;

364f63817a6082042b81f2a1f9bade48.png

第三步: + 则将栈顶的数字3取出,此时栈顶为100 再将数字100取出,将相加后的结果103入栈;

9e1cd0ae2bb4ae8d84f89c757176c8de.png

第四步:数字2入栈;

1fd7bdbab966ba25758080172dc5ef90.png

第五步:+ 将栈顶数字2取出,继续取出栈顶数字103,将相加后的结果105入栈;

085d086337d275e6e833fbcced1c79c3.png

第六步:200入栈;

c77b5ad2d96fdebd3693272076ce49cb.png

第七步:- 将栈顶数字200 取出,继续取出栈顶数字105 将相减后结果 -95 入栈;

第八步:数字10000入栈;

第九步:数字5入栈;

第十步:/ 将栈顶数字5 取出 继续取出栈顶数字10000,计算结果为2000,将2000入栈;

第十一步:数字100入栈;

第十二步:数字2入栈;

第十三步:/ 栈顶数字 2 和栈顶数字100 结果为50 入栈;

第十四步:+ 栈顶数字50 和栈顶数字 2000 计算结果为2050 入栈;

第十五步:+ 栈顶数字2050 和栈顶数字-95 计算结果为 1955 入栈;

第十六步:遍历结束,取出栈顶数字 1955

20e40864b9f9ca853f1c23fe90a69a45.png

d11430733813ed8e361fc9bc7a558141.png

至此结果已经出来了,最终的计算结果为1955

现在来解释刚刚的疑问,后缀表达式该怎么来生成呢??

好了现在我们来一点一点解开未解之谜

1.中缀表达式从左往右遍历,遇到数字则输出

2. 遇到左括号,入栈;遇到右括号 则从栈顶取 一直到取到左括号为止;遇到运算符,优先级不低于当前符号出栈并输出,直到取到比当前优先级低为止(+,-优先级相等,* / 优先级相等,+- 优先级低于 * /)

3.表达式遍历结束 栈内符号依次出栈

还是刚刚的表达式:100+3+2-200+(10000/5+(100/2))

我们来按照这个步骤来分析一下

先创建一个空栈

第一步:数字100输出;

第二步:+ 入栈;

第三步:数字3 输出;

第四步:+ 栈中没有优先级比+低 故栈中+出栈输出,此处+入栈;

6b2978c8bacae88a45a0d1cbc1e36ee6.png

第五步:数字2输出;

第六步:- 栈中没有优先级比-低 故栈中+出栈输出,此处-入栈;

e1e0bb5cdd9f7507a2c546ff2da5f777.png

第七步:数字200 输出;

第八步:+ 栈中没有优先级比+低 故栈中-出栈输出,此处+ 入栈;

6dabcc96d682cb464212659b9fa9e948.png

第九步:符号(入栈;

d26b46dbd71f2676f20369175acbadb0.png

第十步:数字10000输出;

第十一步:/ 栈中+ (优先级都没有/ 高 故/入栈;

82f35ba386305383d56e218cabaa76ea.png

第十二步:数字5 输出;

第十三步:+ 栈顶为/ 优先级高于+ 故+ 入栈/出栈输出;

1ecc085b9c1bc6c757ac0b7c490d71d1.png

第十四步:(入栈;

dc4cf361807f790255be8d1a1c97ac8f.png

第十五步:数字 100 输出;

第十六步:/ 栈顶为( 此处/入栈;

ff95a7f0a8859f457b50729ecad1f533.png

第十七步:数字2 输出;

第十八步:),找到栈顶最近的(之间的符号/出栈输出,(出栈;

4d6735cfc2eabdc8a81ed6026af4ba47.png

第十九步:),到最近的(之间的符号+出栈输出,(出栈;

b63858da1d0638937a27bdd0a4894753.png

第二十步:遍历结束,栈中依次出栈+;

从上往下 背景标红部分为后缀表达式的输出顺序

下面为java代码实现 仅供参考

package com.fx.hfirst.strategy;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Stack;

import java.util.regex.Pattern;

public class Compute {

/**

* @param args

*/

public static void main(String[] args) {

String data = "100+3+2-200+(10000/5+(100/2))";

String[] dataArray = getDataArray(data);

String[] postfixArray = getPostFix(dataArray);

computeWithPostFix(postfixArray);

}

private static String[] getDataArray(String data) {

if (data == null || "".equals(data.trim()) || data.trim().length() < 1) {

return null;

}

int dataLength = data.length();

String[] dataArray = new String[dataLength];// 根据字符串的长度创建数组

int top = 0;

String numStr = "";

for (int i = 0; i < dataLength; i++) {

char datai = data.charAt(i);

String num = String.valueOf(datai);

if (isNum(num)) {// 数字

numStr += num;

if (i + 1 == dataLength) {

dataArray[top] = numStr;

top++;

}

} else {

if (!"".equals(numStr)) {// numStr 存在

dataArray[top] = numStr;// 数字存放到结果数组中

numStr = "";// 还原

top++;// 指针下移

}

// 符号

dataArray[top] = num;

top++;// 指针下移

}

}

return removeNull(dataArray, top);

}

/**

* 获取后缀表达式

*

* @param data

* @return

*/

private static String[] getPostFix(String[] dataArray) {

if (dataArray == null || dataArray.length < 1) {

return null;

}

// 1.遍历数组 数字输出

// 2.若是符号 则判断和栈顶符号的优先级 是右括号 或者优先级低于栈顶符号(乘除高于加减)则栈顶元素依次出栈 输出 并将当前符号入栈

// 3.数组结束 栈内符号依次出栈

int dataLength = dataArray.length;

Stack dataStack = new Stack();

String[] dataBuffer = new String[dataLength];

int top = 0;

for (int i = 0; i < dataLength; i++) {

String datai = dataArray[i];

if (isNum(datai)) {// 数字

dataBuffer[top] = datai;

top++;// 指针下移

} else if (isLeftBracket(datai)) {// 左括号

dataStack.push(datai);// 压栈

} else if (ComputeEnum.isCompute(datai)) {// 运算符

List lessThenMeList = getNotLessThenMeta(dataStack,

datai);

if (lessThenMeList != null && !lessThenMeList.isEmpty()) {

for (String lessThen : lessThenMeList) {// 小于当前运算符的符号输出

dataBuffer[top] = lessThen;

top++;// 指针下移

}

}

dataStack.push(datai);// 当前元素入栈

} else if (isRightBracket(datai)) {// 右括号 查找到最近左括号之间的所有符号 出栈

List betweenLeftBracketList = getBetweenLeftBracketMeta(dataStack);

if (betweenLeftBracketList != null

&& !betweenLeftBracketList.isEmpty()) {

for (String between : betweenLeftBracketList) {// 小于当前运算符的符号输出

dataBuffer[top] = between;

top++;// 指针下移

}

}

} else {

System.err.println("请注意中英文符号,检查出包含不支持的运算符!");

return null;

}

}

while (!dataStack.isEmpty()) {

dataBuffer[top] = dataStack.pop();

top++;// 指针下移

}

return removeNull(dataBuffer, top);

}

// 根据后缀表达式计算出结果 并打印

private static void computeWithPostFix(String[] postfixArray) {

if (postfixArray == null || postfixArray.length < 1) {

System.err.println("postfixArray is null !");

return;

}

// 1.遇到数字则入栈

// 2.遇到运算符号 则将栈顶两元素出栈

// 3.将运算结果入栈

// 4.数组遍历结束 将栈顶元素 取出

Stack stack = new Stack();

for (String meta : postfixArray) {

if (isNum(meta)) {// 数字

stack.push(meta);

} else if (ComputeEnum.isCompute(meta)) {// 运算符号

double pop = Double.parseDouble(stack.pop());

double popNext = Double.parseDouble(stack.pop());

double result = compute(pop, popNext, meta);

stack.push(String.valueOf(result));

}

}

System.out.println("运算结果为:" + stack.pop());

}

private static double compute(double pop, double popNext, String meta) {

double result = 0;

ComputeEnum compute = ComputeEnum.get(meta);

switch (compute) {

case plus:// 加

result = popNext + pop;

break;

case minus:// 减

result = popNext - pop;

break;

case multiply:// 乘

result = popNext * pop;

break;

case divide:// 除

if ((pop < 0.000000001) && (pop > -0.000000001)) {

System.err.println("被除数不能为0!");

break;

}

result = popNext / pop;

break;

}

return result;

}

private static List getBetweenLeftBracketMeta(

Stack dataStack) {

if (dataStack == null || dataStack.size() < 1) {

return null;

}

List list = new ArrayList(dataStack.size());

while (!dataStack.isEmpty()) {

String pop = dataStack.pop();// 栈顶元素出栈

if (isLeftBracket(pop)) {

break;

}

list.add(pop);

}

return list;

}

/**

* 取出所有不比自己优先级低的元素

*

* @param dataStack

* @param datai

* @return

*/

private static List getNotLessThenMeta(Stack dataStack,

String datai) {

if (dataStack == null || dataStack.size() < 1) {

return null;

}

ComputeEnum computei = ComputeEnum.get(datai);

List list = new ArrayList(dataStack.size());

while (!dataStack.isEmpty()) {

String pop = dataStack.peek();// 栈顶元素

ComputeEnum compute = ComputeEnum.get(pop);

if (compute == null) {

break;

}

if (compute.level < computei.level) {

break;

} else {// 优先级高于当前符号 出栈

dataStack.pop();

list.add(pop);

}

}

return list;

}

private static String[] removeNull(String[] dataArray, int size) {

String[] dataResult = new String[size];

System.arraycopy(dataArray, 0, dataResult, 0, dataResult.length);

return dataResult;

}

private static boolean isNum(String num) {

String reg = "^\\d+$";

return Pattern.compile(reg).matcher(num).find();

}

/**

* 左括号

*

* @param num

* @return

*/

private static boolean isLeftBracket(String num) {

return "(".equals(num);

}

/**

* 右括号

*

* @param num

* @return

*/

private static boolean isRightBracket(String num) {

return ")".equals(num);

}

}

enum ComputeEnum {

plus("+", 0), // 加法

minus("-", 0), // 减法

multiply("*", 1), // 乘法

divide("/", 1), // 除法

;

private static Map dataMap = new HashMap();

static {

dataMap.put(plus.code, plus);

dataMap.put(minus.code, minus);

dataMap.put(multiply.code, multiply);

dataMap.put(divide.code, divide);

}

public String code;

public int level;

private ComputeEnum(String code, int level) {

this.code = code;

this.level = level;

}

public static ComputeEnum get(String code) {

return dataMap.get(code);

}

public static boolean isCompute(String code) {

return dataMap.containsKey(code);

}

}

博客中若有错误,欢迎指正,我们一起来共同完善!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java integer valueof_对 Java Integer.valueOf() 的一些了解

从一道选择题开始分析选项A选项A中比较的是i01和i02&#xff0c;Integer i0159这里涉及到自动装箱过程&#xff0c;59是整型常量&#xff0c;经包装使其产生一个引用并存在栈中指向这个整型常量所占的内存&#xff0c;这时i01就是Integer 的引用。而int i0259由于int是基本类型…

java web 伪静态_【Java Web】使用URLRewrite实现网站伪静态

大部分搜索引擎都会优先考虑收录静态的HTML页面&#xff0c;而不是动态的*.jsp、*.php页面。但实际上绝大部分网站都是动态的&#xff0c;不可能全部是静态的HTML页面&#xff0c;因此互联网上大部分网站都会考虑伪静态——就是将*.jsp、*.php这种动态URL伪装成静态的HTML页面。…

使用Spring WebFlux从Corda节点流式传输数据

自上次发布以来已经有一段时间了&#xff0c;但我终于回来了&#xff01; 由于我仍在我的项目中&#xff0c;因此我将再次撰写有关使用Corda的文章。 这次&#xff0c;我们将不再关注Corda&#xff0c;而是将Spring与Corda结合使用。 更具体地说&#xff0c;Spring WebFlux。 为…

mysql 批量加索引_mysql优化:按期删数据 + 批量insert + 字符串加索引为何很傻

嗯&#xff0c;犯了一个很低级的错误&#xff0c;最近暴露出来了。html背景&#xff1a;mysql1. 内部平台&#xff0c;接口间断性无返回&#xff0c;查询日志注意到失败时&#xff0c;接口耗时达到4000(正常状态&#xff1a;100ms)git2. 增长日志打点&#xff0c;在关键步骤插入…

MySQL中引入存储引擎意义是_mysql学习九:存储引擎、存储过程和函数的引入

存储引擎&#xff1a;存储引擎是mysql特有的&#xff0c;共有7种&#xff0c;常用的有myisam、memory、innodb查看表的存储引擎&#xff1a;show create table 表名;修改表的存储引擎&#xff1a;alter table 表名 engine存储引擎名称;1.myisam存储引擎&#xff1a;可转换为压缩…

python土味情话_土味情话表情包下载

喵星人土味情话表情包是一款很甜的表情图片&#xff0c;现在的聊天模式三句话离不开表情包&#xff0c;而且小编带来的这款表情包非常的适合情侣日常撩&#xff0c;最新的土味情话&#xff0c;需要的朋友可以前来本站下载。土味情话大全一、“对不起。”“你永远都不要和我说对…

多云互操作性!=云服务聚合

多云定义为一种方法&#xff0c;它将来自多个云供应商的多个云&#xff08;公共云或私有云&#xff09;组合在一起。 但是&#xff0c;这不是来自不同供应商的各种服务的集合&#xff0c;它需要一种强制性的胶合剂–云不可知的方法&#xff0c;并在所有提供商之间实现互操作性。…

如何在Spring中将@RequestParam绑定到对象

您是否在请求映射方法中用RequestParam注释了多个参数&#xff0c;并认为它不可读&#xff1f; 当请求中需要一个或两个输入参数时&#xff0c;注释看起来非常简单&#xff0c;但是当列表变长时&#xff0c;您可能会感到不知所措。 您不能在对象内部使用RequestParam批注&…

webstorm前端调用后端接口_软件测试面试题:怎么去判断一个bug是前端问题还是后端问题...

大家好&#xff0c;在软件测试面试过程中&#xff0c;经常有面试官问到这个问题&#xff0c;那我们应该如何回答才好呢&#xff1f;少废话&#xff0c;直接看答案&#xff1a;答案&#xff1a;在页面上发现bug之后&#xff0c;要想判断这个问题属于后端还是前端&#xff0c;我就…

首次适应算法_CVPR 2020丨?商汤TSD目标检测算法获得Open Images冠军

编者按&#xff1a;此前&#xff0c;在文章《商汤科技57篇论文入选ICCV 2019&#xff0c;13项竞赛夺冠》里&#xff0c;商汤君报道了商汤科技荣获Open Images Object Detection Challenge 2019 冠军。由Google AI主办的Open Images大赛是目前通用物体检测和实例分割两个领域中数…

玩JDK 12的Switch表达式

在博客文章“操作中的JDK语言功能预览&#xff1a;切换表达式 ”中&#xff0c;我讨论了JEP 325 [“切换表达式&#xff08; 预览 &#xff09;”&#xff09;如何作为指定的“ 预览语言功能 ”的早期应用&#xff0c;如JEP 12所述。预览语言和VM功能”]。 JEP 325 适用于JDK 1…

python 验证码_4行Python代码生成图像验证码

点击上方蓝色字体&#xff0c;关注我们最近无意看到网上有人使用Python编写几十行代码生成图像验证码&#xff0c;感觉很是繁琐&#xff0c;这里为各位朋友推荐两种方法&#xff0c;使用4行Python代码即可生成验证码。1captcha库第1步&#xff1a;安装captcha库pip install cap…

python3 多线程_Python3多线程爬虫实例讲解

多线程概述多线程使得程序内部可以分出多个线程来做多件事情&#xff0c;充分利用CPU空闲时间&#xff0c;提升处理效率。python提供了两个模块来实现多线程thread 和threading &#xff0c;thread 有一些缺点&#xff0c;在threading 得到了弥补。并且在Python3中废弃了thread…

java多条件组合查询6_elasticsearch组合多条件查询实现restful api以及java代码实现

elasticsearch组合多条件查询实现restful api以及java代码实现实际开发中&#xff0c;基本都是组合多条件查询。elasticsearch提供bool来实现这种需求&#xff1b;主要参数&#xff1a;must文档 必须 匹配这些条件才能被包含进来。must_not文档 必须不 匹配这些条件才能被包含进…

基于java家教管理系统_基于jsp的家教信息管理-JavaEE实现家教信息管理 - java项目源码...

基于jspservletpojomysql实现一个javaee/javaweb的家教信息管理, 该项目可用各类java课程设计大作业中, 家教信息管理的系统架构分为前后台两部分, 最终实现在线上进行家教信息管理各项功能,实现了诸如用户管理, 登录注册, 权限管理等功能, 并实现对各类家教信息管理相关的实体…

如何从云功能调用外部REST API

在之前的博客文章中&#xff0c;我展示了如何创建您的第一个云功能 &#xff08;以及一个视频 &#xff09;。 您的云函数很可能需要调用外部REST API。 以下教程将向您展示如何创建此类功能&#xff08;非常简单&#xff09;。 登录到IBM Cloud帐户 点击目录 删除标签&…

机器学习分类算法_机器学习分类算法

人们曾在自身的神经元得到启发&#xff0c;将机器学习中给出的特征输入与权重之积作为输出与阈值作比较&#xff0c;得到0或者1的输出。这就是我们感知器的实现原理感知器在实现过程中的步骤如下&#xff1a;①将权值初始化称为一个很小的向量②迭代训练所有样本&#xff1a;计…

apache camel_Apache Camel –从头开始开发应用程序(第1部分/第2部分)

apache camel开始之前 前段时间&#xff0c;我写了一篇关于Spring Integration的教程&#xff0c;以演示如何在受现实发票处理系统启发的示例应用程序中使用Spring Integration。 我对此非常满意&#xff0c;因此我决定向您展示如何使用Apache Camel&#xff08;Spring Integra…

weblogic创建域后启动不了_摩托车淋雨后启动不了什么原因?如何解决?

图文是工作&#xff0c;视频是生活。大家好&#xff0c;我是 骑士分享 欢迎您的关注&#xff01;摩托车淋雨后启动不了什么原因&#xff1f;如何解决&#xff1f;这种现象对于电喷车型来说发生的几率并不大&#xff0c;原因就在于电喷车型的线路防水能力会更强&#xff0c;供油…

前端开始学java_[Java教程]开启前端学习之路

[Java教程]开启前端学习之路0 2014-06-10 17:00:06前言第一次在博客园写博客&#xff0c;写写自己开启前端学习之路。应该是受邢师兄的影响吧&#xff0c;不得不说邢师兄人很好&#xff0c;学习也很认真&#xff0c;师兄的前端也是自学的&#xff0c;但是学的很好&#xff0c;大…