C++实现计算复杂数学表达式

本文使用C++实现Shunting-yard算法,将中缀表达式转换为后缀表达式,然后使用后缀表达式计算结果,实现了目前支持以下

  • 四则运算(+、-、*、/)
  • 开平方(^)
  • 取基数为 10 的对数(L)
  • 小括号

的组合,实现代码如下

#include <iostream>  
#include <stack>  
#include <string>  
#include <vector>  
#include <cctype>
#include <math.h>/*** @brief getPrecedence 判断优先级* @param op 操作符* @return 0是特殊的,最高优先级,其他的数字越大,优先级越高*/
int getPrecedence(char op) {if (op == '+' || op == '-') {return 1;}else if (op == '*' || op == '/') {return 2;}else if (op == '^'){return 3;}else {return 0;}
}/*** @brief isOperator 判断字符是否是运算符* @param c* @return 是返回true*/
bool isOperator(char c) {return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
}/*** @brief shuntingYard Shunting-yard 算法*  用于将中缀表达式(如 "3 + 4 * 2")转换为后缀表达式(逆波兰表示法,如 "3 4 2 * +")的算法* @param expression 中缀表达式* @return 后缀表达式*/
std::vector<std::string> shuntingYard(const std::string& expression) {std::stack<std::string> operators;std::vector<std::string> output;for (size_t i = 0; i < expression.length(); ++i) {char c = expression[i];if (std::isspace(c)) {continue; // Skip whitespace  }else if (isdigit(c) || (c == '.' && (i == 0 || !isdigit(expression[i - 1])))) {std::string number;while (i < expression.length() && (isdigit(expression[i]) || expression[i] == '.')) {number += expression[i++];}output.push_back(number);--i; // Because the for loop also increments i  }else if (isOperator(c)) {while (!operators.empty() && getPrecedence(c) <= getPrecedence(operators.top()[0])) {output.push_back(operators.top());operators.pop();}operators.push(std::string(1, c));}else if (c == '(') {operators.push("(");}else if (c == ')') {while (!operators.empty() && operators.top() != "(") {output.push_back(operators.top());operators.pop();}if (!operators.empty()) {operators.pop(); // Remove the '(' from the stack  }}else if (c == 'L'){operators.push("L");}else {std::cerr << "Error: Unexpected character '" << c << "'" << std::endl;return {};}}// Push any remaining operators to the output  while (!operators.empty()) {output.push_back(operators.top());operators.pop();}return output;
}/*** @brief evaluatePostfix 计算后缀表达式的结果* @param postfix 后缀表达式* @return 计算结果*/
double evaluatePostfix(const std::vector<std::string>& postfix) {std::stack<double> values;for (const std::string& token : postfix) {if (isOperator(token[0])) {double val2 = values.top(); values.pop();// 防止表达式中有负数导致程序崩溃double val1 = 0.0;if (values.size() > 0){val1 = values.top();values.pop();}double result;switch (token[0]) {case '+': result = val1 + val2; break;case '-': result = val1 - val2; break;case '*': result = val1 * val2; break;case '/':if (val2 == 0) throw std::invalid_argument("Division by zero");result = val1 / val2; break;case '^': result = pow(val1, val2); break;default: throw std::invalid_argument("Invalid operator");}// 显示计算过程std::cout << val1 << token[0] << val2 << "=" << result << std::endl;values.push(result);}else if (token[0] == 'L'){double val = values.top(); values.pop();double result = log10(val);values.push(result);std::cout << "Log10(" << val << ")=" << result << std::endl;}else {values.push(std::stod(token));}}return values.top();
}int main() {std::string infix;std::cout << "Enter an infix expression: ";std::getline(std::cin, infix);while (infix.size() > 0){try{std::vector<std::string> postfix = shuntingYard(infix);// 打印后缀表达式用于验证  std::cout << "Postfix expression: ";for (const auto& token : postfix) {std::cout << token << " ";}std::cout << std::endl;double result = evaluatePostfix(postfix);std::cout << "Result: " << result << std::endl;}catch (const std::exception& e) {std::cerr << "Error: " << e.what() << std::endl;}infix = "";std::cout << "Enter an infix expression: ";std::getline(std::cin, infix);}return 0;
}

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

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

相关文章

小(2)型土石坝安全监测设施配置详解

小(2)型土石坝的安全监测是确保大坝稳定、安全运行的重要环节。为此&#xff0c;合理配置安全监测设施显得尤为重要。以下是对小(2)型土石坝安全监测设施配置的详细介绍。 一、渗流量监测 渗流量是反映大坝安全状况的关键指标之一。为准确监测渗流量&#xff0c;我们采用仪器量…

【大数据】Flink SQL 语法篇(十):EXPLAIN、USE、LOAD、SET、SQL Hints

《Flink SQL 语法篇》系列&#xff0c;共包含以下 10 篇文章&#xff1a; Flink SQL 语法篇&#xff08;一&#xff09;&#xff1a;CREATEFlink SQL 语法篇&#xff08;二&#xff09;&#xff1a;WITH、SELECT & WHERE、SELECT DISTINCTFlink SQL 语法篇&#xff08;三&…

day05_用户管理minIO角色分配(页面制作,查询用户,添加用户,修改用户,删除用户,用户头像,查询所有角色,保存角色数据)

文章目录 1 用户管理1.1 页面制作1.2 查询用户1.2.1 需求说明1.2.2 后端接口需求分析SysUserSysUserDtoSysUserControllerSysUserServiceSysUserMapperSysUserMapper.xml 1.2.3 前端对接实现思路sysUser.jssysRole.vue 1.3 添加用户1.3.1 需求说明1.3.2 页面制作1.3.3 后端接口…

ChatGPT-4 AI 绘图魔力释放

最近刚开通了 ChatGPT4&#xff0c;正好要设计一个网站图标&#xff0c;想测试一下它AI绘图的能力&#xff0c;让它根据文字描述生成一个想象中的图标 &#xff08;PS&#xff1a;如果想体验 GPT4 文生图&#xff0c;可以看这个教程 如何升级 ChatGPT 4.0&#xff09; 第1次交…

【三维重建】【SLAM】SplaTAM:基于3D高斯的密集RGB-D SLAM

题目&#xff1a;SplaTAM: Splat, Track & Map 3D Gaussians for Dense RGB-D SLAM 地址&#xff1a;spla-tam.github.io 机构&#xff1a;CMU&#xff08;卡内基梅隆大学&#xff09;、MIT&#xff08;美国麻省理工&#xff09; 总结&#xff1a;SplaTAM&#xff0c;一个新…

ywtool network命令

一.network功能介绍 network功能就是通过脚本的方式配置IP信息&#xff0c;分为4项: (1) 配置单网卡(2)配置br网桥(单网卡)(3)配置bond(两张网卡)(4)配置ovs网桥(单网卡) 日志文件:/var/log/ywtools/ywtools-network.log/usr/local/ywtools/config/config.ini中network参数:…

从预训练到通用智能(AGI)的观察和思考

1.预训练词向量 预训练词向量&#xff08;Pre-trained Word Embeddings&#xff09;是指通过无监督学习方法预先训练好的词与向量之间的映射关系。这些向量通常具有高维稠密特征&#xff0c;能够捕捉词语间的语义和语法相似性。最著名的预训练词向量包括Google的Word2Vec&#…

Go语言实战五-go语言的类型与iton

前言 go语言是静态类型语言&#xff0c;也就是在编译时编译器需要知道程序中值的类型&#xff0c;这样有利于减少bug和提高性能&#xff0c;具体就是内存的分配量和其中的内容 用户定义类型 1.用户定义新的类型&#xff0c;需要使用type 和struct关键字 type user struct {…

项目实现json字段

有些很复杂的信息&#xff0c;我们一般会用扩展字段传一个json串&#xff0c;字段一般用text类型存在数据库。mysql5.7以后支持json类型的字段&#xff0c;还可以进行sql查询与修改json内的某个字段的能力。 1.json字段定义 ip_info json DEFAULT NULL COMMENT ip信息, 2.按…

应用存储与持久化数据卷

1、PV 引入场景&#xff1a; ① Deployment 管理的 pod&#xff0c;在做镜像升级的过程中&#xff0c;会产生新的 pod并且删除旧的 pod &#xff0c;新旧 pod 之间如何复用数据&#xff1f; ② 宿主机宕机的时候&#xff0c;如何实现带卷迁移&#xff1f; ③ 多个 pod 之间&…

Redis 之三:发布订阅(pub/sub)

概念介绍 Redis 发布订阅 (pub/sub) 是一种消息通信模式&#xff0c;它允许客户端之间进行异步的消息传递 Redis 客户端可以订阅任意数量的频道。 模型中的角色 在该模型中&#xff0c;有三种角色&#xff1a; 发布者&#xff08;Publisher&#xff09;&#xff1a;负责发送信…

[分类指标]准确率、精确率、召回率、F1值、ROC和AUC、MCC马修相关系数

准确率、精确率、召回率、F1值 定义&#xff1a; 1、准确率&#xff08;Accuracy&#xff09; 准确率是指分类正确的样本占总样本个数的比例。准确率是针对所有样本的统计量。它被定义为&#xff1a; 准确率能够清晰的判断我们模型的表现&#xff0c;但有一个严重的缺陷&…

《Docker极简教程》--Docker在生产环境的应用--Docker在生产环境的监控

一、Docker监控的基本概念 1.1 容器监控 vs 主机监控 在 Docker 环境中&#xff0c;监控是确保系统稳定性和性能的关键活动之一。在监控 Docker 环境时&#xff0c;我们通常会关注容器监控和主机监控两个方面。 容器监控&#xff1a; 容器监控是指监视 Docker 容器本身的运行…

在Windows系统中启动Redis服务

前言 Redis是一个开源、高性能的键值对数据库&#xff0c;常用于缓存、消息队列等场景。本文将详细指导您如何在Windows系统上启动Redis服务。 第一步&#xff1a;确认Redis安装 确保您已经在Windows系统上成功安装了Redis。官方提供了预编译好的Windows版本&#xff0c;您可…

低代码中的可视化表单:效率与灵活兼备的设计工具

近年来&#xff0c;随着数字化转型的加速推进&#xff0c;企业对于高效率、灵活性和可定制性的软件开发需求不断增长。传统的软件开发过程通常需要耗费大量的时间和资源&#xff0c;而低代码开发平台的出现为企业提供了一种更加快速和灵活的解决方案。在低代码开发平台中&#…

Linux centos 变更MySQL数据存储路径

Linux centos 变更MySQL数据存储路径 登录mysql&#xff0c;查看数据存储路径创建新目录准备迁移数据检查是否配置成功 登录mysql&#xff0c;查看数据存储路径 mysql -u root -pshow global variables like "%datadir%";创建新目录 查看磁盘空间 df -h选取最大磁…

Android 11.0 framework系统修改安兔兔等显示的屏幕尺寸大小功能实现

1.前言 在11.0的系统rom定制化开发中,在使用第三方app检测系统的一些信息中,比如安兔兔 设备信息等检测app中,有时候显示的屏幕尺寸大小和 产品规格书等信息不同,稍微有些差异,所以就需要看下系统framework层中,相关的设备信息是怎么读出来的,然后做些调整 接下来就来分…

不可多得的干货,网易的朋友给我这份339页的Android面经

这里先放上目录 一 性能优化 1.如何对 Android 应用进行性能分析 android 性能主要之响应速度 和UI刷新速度。 首先从函数的耗时来说&#xff0c;有一个工具TraceView 这是androidsdk自带的工作&#xff0c;用于测量函数耗时的。 UI布局的分析&#xff0c;可以有2块&#x…

本届挑战赛亚军方案:基于大模型和多AGENT协同的运维

“轻舟已过万重山团队”荣获本届挑战赛亚军&#xff0c;该团队来自华为集团IT-UniAI 产品和openEuler系统智能团队。 方案介绍 自ChatGPT问世以来&#xff0c;AI迎来了奇点iPhone时刻&#xff0c;这一年来大模型深入影响企业办公&#xff0c;金融&#xff0c;广告&#xff0c;…

打造去中心化透明储蓄罐:Solidity智能合约的又一实践

一、案例背景 传统的储蓄罐通常是由个人或家庭使用&#xff0c;用于存放硬币或小额纸币。然而&#xff0c;这样的储蓄罐缺乏透明性&#xff0c;用户无法实时了解储蓄情况&#xff0c;也无法确保资金的安全性。 通过Solidity智能合约&#xff0c;我们可以构建一个去中心化…