当前位置: 首页 > news >正文

没有括号的字符串四则运算

目录

  • 问题
  • 分析与解答
  • eval
  • sympy
  • 消去法
  • 逆波兰表达式
  • 拓展思考
  • 参考资料

问题

用代码实现一个method,这个method的入参是一个字符串,这个字符串是一个四则运算的算式,比如“1+2*3+4/2-3”;返回值是这个算式的运算结果,比如“1+2*3+4/2-3”的返回值是6,为了简化这个题目,这个入参的算式只包含加减乘除,不包含括号

分析与解答

四则运算是数学常见的运算法则,有现成的函数或者第三方库来解决,也可以自己写一个method。下面分别介绍几种方法,按照由易到难的顺序

eval

由于入参的算式只包含加减乘除,不包含括号,所以可以采用eval直接算,但是eval会存在注入风险。

# -*- encoding: utf-8 -*-
'''
@Project :   Arithemitc
@Desc    :   字符串转四则运算
@Time    :   2024/05/25 09:28:12
@Author  :   帅帅de三叔,zengbowengood@163.com
'''
import re
import operatordef arithmetic(expression):"""eval直接算"""return eval(expression)if __name__=="__main__":input = "1+2-3/2*2" #例子1+2-3/2*2, 1+2*3+4/2-3result = arithmetic(input)print(result)

sympy

sympy 是专用的数学符号计算库,在处理方程时候非常强大,但是运行效率稍微慢了点

import re
import operator
from sympy import sympify, simplifydef Arithemtic(origin_str): """去除优先级乘法和除法运算"""expr = str(origin_str) #转字符串result = simplify(sympify(expr))return resultif __name__=="__main__":input = "1+2-3/2*2" #1+2-3/2*2result = Arithemtic(input)print(result)

消去法

倘若优先级运算“x”和“/”不相邻,此时,可以先对“x"和”/“先单独计算把“x"和”/“前后两个数字先计算和合二为一,处理完就只有”+“和”-“两种运算了,下面这个可以实现“x”和“/”不相邻的情形,“x”和“/”相邻的情况还没想好。

# -*- encoding: utf-8 -*-
'''
@Project :   Arithemitc
@Desc    :   字符串转四则运算
@Time    :   2024/05/25 09:28:12
@Author  :   帅帅de三叔,zengbowengood@163.com
'''
import re
import operatordef Arithemtic(origin_str): """去除优先级乘法和除法运算"""expr = str(origin_str) #转字符串digits = re.findall(r'\d+', expr) #提取数字串digits = [eval(i) for i in digits] #转数字operations = re.findall(r'[+\-*/]', expr) #提取运算符号print(digits, operations)operators = {'+': operator.add, '-': operator.sub, '*': operator.mul, '/': operator.truediv} #四则运算映射for i in range(len(operations)): #对运算列表循环try:if operations[i] == "*" or operations[i] =="/": #如果有乘法,除法,先算去除print(i, operations[i], digits[i], digits[i+1])digits[i] = operators[operations[i]](digits[i], digits[i+1]) #合并运算print(digits, operations)digits.pop(i+1) #剔除第i+1位数字operations.pop(i) #剔除第i位算符  except:continueprint(digits, operations)  #此时只有加减运算for j in range(len(operations)): # print(digits[j])     digits[j+1] =  operators[operations[j]](digits[j], digits[j + 1]) #咬合向前逐步运算result = digits[-1]print(result)return resultif __name__=="__main__":input = "1+2*3+4/2-3" #1+2-3/2*2result = Arithemtic(input)

逆波兰表达式

查阅资料说逆波兰表达式法可以用于解决没有括号的字符串四则运算,计算步骤如下:

1,字符串四则运算表达式转换为后缀表达式
2,从左到右遍历表达式中的每个元素;
3,如果当前元素是数字,将其压入栈中;
4,如果当前元素是运算符,则取出栈顶的两个数字进行计算,并将结果压入栈中;
5,当遍历完整个表达式后,栈顶就是最终结果。

import redef infix_to_postfix(expression):  # 运算符优先级字典,越低越优先  precedence = {'+': 1, '-': 1, '*': 2, '/': 2}  output = []  op_stack = []  # 辅助函数,用于检查是否为运算符  def is_operator(token):  return token in '+-*/'  # 分割表达式为tokens  tokens = re.findall(r'[+\-*/]|\d+', expression)    for token in tokens:  if token.isdigit():  # 如果是数字,直接输出  output.append(token)  elif is_operator(token):  # 如果是运算符  # 弹出并输出所有优先级更高或等于当前运算符的运算符  while op_stack and is_operator(op_stack[-1]) and \precedence[op_stack[-1]] >= precedence[token]:  output.append(op_stack.pop())  # 将当前运算符压入栈  op_stack.append(token)  else:  # 如果是非法字符,抛出异常  raise ValueError(f'Invalid token: {token}')  # 弹出并输出所有剩余的运算符  while op_stack:  output.append(op_stack.pop())  return ' '.join(output)  def evaluate_postfix(postfix_expr):  stack = []  for token in postfix_expr.split():  # 假设表达式是空格分隔的字符串  if token.isdigit():  # 如果是数字  stack.append(int(token))  else:  # 如果是运算符  operand2 = stack.pop()  operand1 = stack.pop()  if token == '+':  result = operand1 + operand2  elif token == '-':  result = operand1 - operand2  elif token == '*':  result = operand1 * operand2  elif token == '/':  # 注意:这里没有处理除数为0的情况  result = operand1 / operand2  else:  raise ValueError(f"Invalid operator: {token}")  stack.append(result)  return stack.pop()  # 返回最终结果  # 示例  
infix_expr = "1+2-3/2*2"   
postfix_expr = infix_to_postfix(infix_expr)  
result = evaluate_postfix(postfix_expr)
print(f"Postfix expression: {postfix_expr}")
print(f"result: {result}")

拓展思考

1,根据乘法与除法的关系,除以某个数等于乘以这个数的倒数,可以将所有除法运算改成乘法运算,这种改变只会改变运算符号的右侧不会动左侧的;

2,根据乘法是加法的简便运算将所有乘法改成加法运算,这里存在一个非整数倍的问题需要用数值解法;

3,最后化成只有加法和减法的表达式,因为是对字符串操作,其中需要用到大量的正则运算和定位索引。

参考资料

1,逆波兰表达式介绍及求值实现
https://blog.csdn.net/wenwenaier/article/details/121236053

相关文章:

没有括号的字符串四则运算

目录 问题分析与解答evalsympy消去法逆波兰表达式拓展思考参考资料 问题 用代码实现一个method,这个method的入参是一个字符串,这个字符串是一个四则运算的算式,比如“12*34/2-3”;返回值是这个算式的运算结果,比如“…...

vue2 $set 后期添加响应式数据的问题,使用vm.$set()

文章目录 后期添加数据的问题后期给Vue的实例添加的属性,会有响应式吗?避免在运行时向vm或其根$data添加响应式 对象的响应式处理想给后期追加的属性添加响应式处理的,有以下俩个方法: 数组的响应式处理解决方案一:解决…...

笔记-X86下用Docker运行ARM64编译Libreoffice

初衷 针对恶略环境下的自适应,记个笔记,苦于没有外网的arm架构环境,内网中安装个arm类型的deb,难如登天,突然发现这个好东西。 参考引用 x86架构的Ubuntu上通过Docker运行ARM架构的系统 前提 docker已经安装好 安…...

力扣:92. 反转链表 II(Java)

目录 题目描述&#xff1a;示例 1&#xff1a;示例 2&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的…...

[less配置]vue2引入less

1、终端输入&#xff1a;npm install less less-loader --save-dev 2、在package.json查看是否安装less依赖 3、调用...

物理内存与虚拟内存的区别

物理内存和虚拟内存是计算机系统中重要的概念&#xff0c;它们有着不同的特点和作用。 物理内存&#xff1a; 物理内存是计算机实际存在的内存&#xff0c;通常指的是RAM&#xff08;随机存取存储器&#xff09;。物理内存直接映射到计算机的物理地址空间&#xff0c;可以直接被…...

MySQL数据库案例实战教程:数据类型、语法与高级查询详解

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…...

操作系统——用户态与内核态、同步与异步、阻塞与阻塞

文章目录 什么是用户态与内核态同步与异步、阻塞与非阻塞四种组合方式 什么是用户态与内核态 计算机系统中&#xff0c;通常 CPU 执行两种不同性质的程序代码&#xff1a;一种是操作系统内核程序&#xff08;管理程序&#xff09;&#xff1b;另一种是用户自编程序&#xff08…...

C# VSTO读取Excel单元格Value、Value2

对单个单元格的值&#xff0c;需要用object 对象去接 object value (object)oneCellRange.Value; object value2 (object)oneCellRange.Value2; 对矩形范围的值&#xff0c;需要用object[,]去接 object[,] matrixValues (object[,])matrixRange.Value; object[,] matrixV…...

如何快速从手动测试转向自动化测试

寻求具有无缝持续集成和持续交付 (CI/CD) 的高效 DevOps 管道比以往任何时候都更加重要。想象一下这样一个场景&#xff1a;您的软件组织显著减少了人工工作量、降低了成本&#xff0c;并更加自信地发布了软件更新。换句话说&#xff0c;通过将 Web UI 和 API 测试结合在一起&a…...

【Linux+Docker】修改Docker容器中的hosts文件

1、进入容器bash docker exec -it <container_id> bash2、安装编辑器 2.1、安装vim apt-get updateapt-get install vim2.2、安装nano apt-get install nano3、编辑hosts文件 3.1、使用vim编辑 vi /etc/hosts3.2、使用nano编辑 nano /etc/hosts4、安装ping apt-get…...

在VS Code中进行Java的单元测试

在VS Code中可以使用 Test Runner for Java扩展进行Java的测试执行和调试。 Test Runner for Java的功能 Test Runner for Java 结合 Language Support for Java by Red Hat 和 Debugger for Java这两个插件提供如下功能&#xff1a; 运行测试&#xff1a; Test Runner for …...

国内信创web中间件生态

国内信创web中间件生态 东方通 官网https://www.tongtech.com/pctype/25.html 宝蓝德 官网https://www.bessystem.com/product/0ad9b8c4d6af462b8d15723a5f25a87d/info?p101 金蝶天燕 官网 https://www.apusic.com/list-117.html 中创 官网http://www.inforbus.com…...

CSS中的writing-mode属性:解锁文本布局新维度

在网页设计的广阔天地里&#xff0c;CSS&#xff08;层叠样式表&#xff09;扮演着至关重要的角色&#xff0c;它赋予了我们塑造网页外观和布局的强大能力。其中&#xff0c;writing-mode属性是一个常被忽视但功能强大的工具&#xff0c;用于控制文本的书写方向和排列方式。今天…...

SQL面试题练习 —— 波峰波谷

来源&#xff1a;字节今日头条 目录 1 题目2 建表语句3 题解 1 题目 有如下数据&#xff0c;记录每天每只股票的收盘价格&#xff0c;请查出每只股票的波峰和波谷的日期和价格&#xff1b; 波峰定义&#xff1a;股票价格高于前一天和后一天价格时为波峰 波谷定义&#xff1a;股…...

检索模型预训练方法:RetroMAE

论文title&#xff1a;https://arxiv.org/pdf/2205.12035RetroMAE: Pre-Training Retrieval-oriented Language Models Via Masked Auto-Encoder 论文链接&#xff1a;https://arxiv.org/pdf/2205.12035 摘要 1.一种新的MAE工作流&#xff0c;编码器和解器输入进行了不同的掩…...

OpenHarmony实战开发——宿舍全屋智能开发指南

项目说明 基于OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;、数字管家开发宿舍全屋智能&#xff0c;实现碰一碰开门、碰一碰开灯、碰一碰开风扇以及烟感检测。因为各项目开发流程大体相似&#xff0c;本文主要以碰一碰开门为例介绍如何在现有OpenHar…...

等了10年,终于迎来RTX5/RTX4全家桶开源,开源,开源! 且免费商用

我们的V4, V5, V6 ,V7开发板都配套了大量的RTX4, RTX5教程和案例&#xff0c;从2015年发布首版RTX4内核教程以来&#xff0c;已经整整10年了。 1、制作这个RTX教程和案例&#xff0c;其实也承受了很大的压力&#xff0c;因为只有RTX内核是免费商用的&#xff0c;中间件并不免费…...

Python 读取.shp文件并生成图幅编号

代码适用于需要处理和分析地理空间数据的场景&#xff0c;如城市规划、环境监测或自然资源管理&#xff0c;其中它可以帮助用户读取特定区域的Shapefile文件&#xff0c;确定其地理边界&#xff0c;并基于这些边界计算出按照经纬度5度间隔的图幅编号&#xff0c;进而用于地图制…...

【算法】位运算算法——判断字符是否唯一

题解&#xff1a;判断字符是否唯一(位运算算法) 目录 1.题目2.题解3.位图参考代码4.细节5.总结 1.题目 题目链接&#xff1a;LINK 2.题解 题解有两种方法&#xff0c; 一是做一个哈希数组&#xff0c;去查重&#xff1b; 二是直接用一个变量每一位来对应表示是否有这个字母…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...