[C++] 配平化学方程式算法的封装
有人已经实现了配平的方法,在此不再重复介绍。
https://www.cnblogs.com/Elfish/p/7631603.html
但是,上述的方法所提供的代码还是存在着问题,需要进一步修改。
首先,因为 frac 这个结构的成员函数和其它操作函数已被声明并定义至一个单一的文件里,
因此,首先要将它的声明和定义分开来。把 frac 结构体抽离至封装的类以外,作为前置声明。
因为原代码是直接 printf() 输出的,而我们需要的是获取它输出的结果。
所以,改变它输出的位置,声明一个 string ,将配好以后的结果直接赋值到 string 里。
最终代码实现:
[C++ 源代码]
1 /* Exzh Cross Platfrom Toolkit (ECPT) Qt Version 2 * (This file is the part of the ECPT Project) 3 * Author: Exzh_PMGI 4 * E-mail: realexzh@gmail.com 5 * License: LGPL v3.0 / Exzh Commerical License 6 * Copyright: (C) Exzh_PMGI 7 * Qt Framework 5.10 has been tested successfully 8 * If you want to use the code for business, 9 * please contact me by my email. 10 */ 11 12 #include "exequationbalancer.h" 13 14 #include <QDebug> 15 16 int gcd(int x, int y) { 17 return x % y == 0 ? y : gcd(y, x%y); 18 } 19 20 int lcm(int x, int y) { 21 return x * y / gcd(x, y); 22 } 23 24 frac createFrac(int a, int b) 25 { 26 frac tmp = { a,b }; 27 return tmp; 28 } 29 30 frac Abs(frac x) { 31 int p = x.a>0 ? x.a : -x.a, q = x.b>0 ? x.b : -x.b; 32 return createFrac(p, q); 33 } 34 35 string exEquationBalancer::getResult(string inputstr) 36 { 37 strcpy(s,inputstr.c_str()); 38 int lst = 0; 39 for (int i = 1;i<strlen(s);i++) { 40 if (i == strlen(s) - 1)scan(lst, i); 41 if (s[i] == '+' || s[i] == '=') 42 { 43 scan(lst, i - 1); 44 lst = i + 1; 45 } 46 if (s[i] == '=')flag = -1; //等号后面的系数变负 47 } 48 if (Solve()) 49 for (int i = 1;i <= c2 - 1;i++) 50 ans[i] = M[i][N + 1]; 51 else output+="No Solution"; 52 int tmp = lcm(ans[1].b, ans[2].b); 53 for (int i = 3;i <= c2;i++)tmp = lcm(tmp, ans[i].b); 54 for (int i = 1;i <= c2;i++)Ans[i] = ans[i].a*tmp / ans[i].b; //取分母Lcm,把分数变整数 55 for (int i = 1;i <= c2;i++) 56 { 57 if (Ans[i]>1) output+=to_string(Ans[i]); 58 for (int j = 0;j<strlen(mat[i]);j++) 59 output+=mat[i][j]; 60 if (i == c2) 61 { 62 return output; 63 qDebug()<<QString::fromStdString(output); 64 } 65 else if (i == c1) output+="="; 66 else output+="+"; 67 } 68 } 69 70 bool exEquationBalancer::Solve() { //解方程 (矩阵 高cnt,宽c2+1,c2+1列常数全0) 71 ans[c2] = 1; //令最后一个解为1 72 for (int i = 1;i <= cnt;i++) { 73 for (int j = 1;j <= c2;j++) 74 M[i][j] = fun[i][j]; 75 } 76 for (int i = 1;i <= cnt;i++) 77 M[i][c2].a = -M[i][c2].a; //移到常数 78 //高斯消元过程 79 N = c2 - 1, K = cnt; 80 for (int k = 1;k <= N;k++) { 81 frac maxm = createFrac(-1, 1); 82 int maxi; 83 for (int i = k;i <= K;i++) 84 if (maxm<Abs(M[i][k])) 85 maxm = Abs(M[i][k]), maxi = i; 86 if (maxm == createFrac(0, 1)) 87 return false; 88 if (maxi != k) 89 for (int j = 1;j <= N + 1;j++) { 90 swap(M[k][j], M[maxi][j]); 91 } 92 frac tmp = M[k][k]; 93 for (int j = 1;j <= N + 1;j++) 94 M[k][j] = M[k][j] / tmp; 95 for (int i = k - 1 ? 1 : 2;i <= K;i++) { 96 if (i == k)continue; 97 frac tmp = M[i][k]; 98 for (int j = 1;j <= N + 1;j++) 99 M[i][j] = M[i][j] - tmp * M[k][j]; 100 } 101 } 102 return true; 103 } 104 105 void exEquationBalancer::scan(int l, int r) { //处理物质 106 c2++; 107 for (int i = 0;i <= r - l;i++)mat[c2][i] = s[l + i]; //存下元素的名字 108 if (flag == 1)c1++; //统计一下反应物数量 109 int tmp = 1; //tmp是小括号倍数 110 for (int i = l;i <= r;i++) { 111 if (s[i] == ')')tmp = 1; 112 if (s[i] == '(') { 113 int j = i + 1;while (s[j] != ')')j++; //找这个括号的范围 114 tmp = getint(j); //读")"右边的数字 115 } 116 if (s[i] >= 'A'&&s[i] <= 'Z') { //发现元素 117 int x = s[i] - 'A' + 1, y = 0; 118 if (s[i + 1] >= 'a'&&s[i] <= 'z') //看一眼是一个字母的还是两个的 119 y = s[i + 1] - 'a' + 1; 120 if (!Map[x][y])Map[x][y] = ++cnt; //判重 121 fun[Map[x][y]][c2] += flag * getint(i)*tmp; //把这个物质里的这种元素数量放进矩阵里,坐标(map[x][y],c2) 122 } 123 } 124 } 125 126 int exEquationBalancer::getint(int pos) { //读数 127 pos++; 128 if (s[pos] >= 'a'&&s[pos] <= 'z')pos++; 129 if (s[pos]<'0' || s[pos]>'9')return 1; //没数就是1 130 else { 131 int x = 0; 132 while (s[pos] >= '0'&&s[pos] <= '9')x = x * 10 + s[pos] - '0', pos++; //读元素后面的数字 133 return x; 134 } 135 } 136 137 void exEquationBalancer::print() { 138 output += to_string(N); 139 output += " "; 140 output += to_string(K); 141 output += "\n"; 142 for (int i = 1;i <= K;i++) { 143 for (int j = 1;j <= N + 1;j++) 144 { 145 output += to_string(M[i][j].a); 146 output += " "; 147 } 148 output += "\n"; 149 } 150 output += "\n"; 151 }
[C++ 头文件]
1 /* Exzh Cross Platfrom Toolkit (ECPT) Qt Version 2 * (This file is the part of the ECPT Project) 3 * Author: Exzh_PMGI 4 * E-mail: realexzh@gmail.com 5 * License: LGPL v3.0 / Exzh Commerical License 6 * Copyright: (C) Exzh_PMGI 7 * Qt Framework 5.10 has been tested successfully 8 * If you want to use the code for business, 9 * please contact me by my email. 10 */ 11 12 #ifndef EXEQUATIONBALANCER_H 13 #define EXEQUATIONBALANCER_H 14 15 #include <string> 16 #include "../exstdc++.h" 17 18 using namespace std; 19 static string output; 20 int lcm(int x, int y); 21 int gcd(int x, int y); 22 23 struct frac { //分数类 24 int a, b; 25 void reduce() { 26 int x = gcd(a, b); 27 a /= x, b /= x; 28 } 29 frac createFrac(int a, int b) 30 { 31 frac tmp = { a,b }; 32 return tmp; 33 } 34 frac operator = (int x) { 35 a = x, b = 1; 36 return *this; 37 } 38 frac operator = (const frac x) { 39 a = x.a, b = x.b; 40 reduce(); 41 return *this; 42 } 43 frac operator + (const frac x) { 44 return createFrac(b*x.a + a * x.b, b*x.b); 45 } 46 frac operator - (const frac x) { 47 return createFrac(a*x.b - b * x.a, b*x.b); 48 } 49 frac operator * (const frac x) { 50 return createFrac(a*x.a, b*x.b); 51 } 52 frac operator / (const frac x) { 53 return createFrac(a*x.b, b*x.a); 54 } 55 bool operator < (const frac x) { 56 return a * x.b<b*x.a; 57 } 58 bool operator == (const frac x) { 59 return a * x.b == b * x.a; 60 } 61 void print() { 62 if (b == 1) 63 { 64 output += to_string(a); 65 output += "\n"; 66 } 67 else 68 { 69 output += to_string(a); 70 output += "/"; 71 output += to_string(b); 72 } 73 } 74 }; 75 76 frac createFrac(int a, int b); 77 frac Abs(frac x); 78 79 class exEquationBalancer 80 { 81 public: 82 string getResult(string inputstr); 83 84 private: 85 bool Solve(); 86 void scan(int l, int r); 87 int getint(int pos); 88 void print(); 89 90 char s[55]; 91 int fun[55][55]; 92 int Map[27][27]; //手动MAP 93 frac M[55][55]; //求解矩阵 94 frac ans[55]; //解 95 int Ans[55]; //整数解 96 int cnt, c1, c2, flag = 1, N, K; //cnt数元素,c1数反应物,c2总数 (未知数的数量) 97 char mat[55][55]; //存储物质的名称 98 }; 99 100 #endif // EXEQUATIONBALANCER_H
转载于:https://www.cnblogs.com/exzhpmgi/p/10089242.html
[C++] 配平化学方程式算法的封装相关推荐
- Python趣用—配平化学方程式
不知不觉已经毕业多年了,不知道大家是否还记得怎么配平化学方程式呢?反正小编我是已经记不太清了,所以今天的文章除了分享如何用python配平化学方程式,顺带着还会复习一些化学方程式的知识,希望广大化学爱 ...
- 配平化学方程式的C++代码实现
配平化学方程式的C++代码实现 纪念一下我今天写过了 20171006. (去年的这个时候我就有了这个大胆的想法, 当时的思路是:字符串处理->暴力搜系数,可是太年轻写不对,我那会还是个只会模拟 ...
- 用Python配平化学方程式
可以使用 Python 的第三方库 Pybel 来配平化学方程式. 首先,需要安装 Pybel,可以使用以下命令进行安装: pipinstall pybel
- 不使用第三方库,用Python配平化学方程式
非常好!我们可以使用 Python 内置的正则表达式库来帮助我们匹配化学方程式. 首先,我们可以使用正则表达式来匹配化学方程式的左右两边. 在这里,我们假设化学方程式的左边是一个或多个化学物质的名称, ...
- 写一段代码,利用Python配平化学方程式
好的,这是一段使用 Python 配平化学方程式的代码: from sympy import symbols, Eq, solve# 定义化学方程式中的化学物质 H2O, H, O = symbols ...
- 用Python配平化学方程式,不使用第三方库
好的,我来向你介绍一种用 Python 配平化学方程式的方法. 首先,我们需要对化学方程式进行分析,将其分解为反应物和生成物.然后,我们需要根据化学反应的化学计量关系来确定每种物质的化学计量数.最后, ...
- 有机物燃烧的化学方程式配平(洛谷P1994题题解,Java语言描述)
题目要求 P1994题目链接 分析 我太菜了,亏得我高中时期还虐(or被虐)生化,如今多年过去竟然没分析出来坑点,我太菜了. 我开始盲目认为"元素守恒",所以对HHH原子数求和, ...
- CCF 2019-12 第三题 化学方程式配平(100分)
题解: 字符串模拟 题目意思很明确就是判断化学方程式是否配平. 基本思路:就是对化学方程式左边和右边的元素进行计数,然后判断所有的元素的数量是否相等即可. 第一步:对字符串进行拆分 ...
- 用python实现化学方程式配平
化学方程式配平是指调整化学反应的化学方程式,使得反应中所有的化学元素的原子数目在反应开始和反应结束时相等. 下面是一个简单的 Python 代码,用于配并化学方程式: ``` python 输入化学方 ...
最新文章
- MCU小tips(提高效率)
- python调用shell命令-在Python中执行shell命令的6种方法,你都知道吗?
- 【Android 高性能音频】OboeTester 音频性能测试应用 ( Oboe 输出测试参数 | API 选择 | 音频输出设备选择 | 采样率 | 通道 | 采样格式 | 播放偏好 )
- 从0到掌握Java泛型有这一篇博客就够了
- 【Qt】数据库用户接口层
- java线程池延期执行一次_Java使用者的延期执行
- C和汇编---while反汇编
- skywalking(1) 基于opentracing规范的APM系统
- 安装scws需要安装php吗,Linux 安装SCWS-1.2.3 安装说明(包括php扩展)
- WSL Arch Linux 已在 Microsoft Store 上可用
- word2vec----CBOW
- 【POJ1442】Black Box
- php关联微信支付宝,php实现微信和支付宝支付
- 自动采集小说程序源码
- 僵尸进程以及如何处理僵尸进程
- Yield Guild Games:播客专题
- 基于CNN的垃圾分类模型
- 【一致性仿真】Consensus Control of Leader-Following Multi-Agent Systems in Directed Topology With ...
- 图书管理系统java课设_JavaGUI图书管理系统(可作课程设计)
- 叮咚买菜2021第四季度财报数据公布:上海地区实现盈利
热门文章
- doker学习4---docker容器数据卷
- LoadRunner性能测试培训大纲
- 【ZT】【详细教程】WPS如何关闭自动更新和WPS热点?(ksomisc.exe)
- 口碑营销:如何让传统行业的电商引发口碑效应并营销
- Linux 自带神器 logrotate 详解
- 【总结】1361- package.json 与 package-lock.json 的关系
- 500万条微博数据来源分析
- Java中进入wait状态的线程被唤醒后会接着上次执行的地方往下执行还是会重新执行临界区的代码
- 三年级计算机老师个人总结,三年级计算机教学工作总结
- 我的Blog——python封装为exe的注意事项(封装exe看这一篇基本就够了)