C++配平化学方程式,附源码。配平化学方程式的C++代码实现

2023-10-29 20:30

本文主要是介绍C++配平化学方程式,附源码。配平化学方程式的C++代码实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

化学方程式是化学反应简明的表达形式,它从“质”和“量”两个方面表达了化学反应的意义。故化学方程式的书写是我们学习化学的过程中不可或缺的一个重要环节。当我们遇到简单的化学方程式例如:2H2 + O2 = 2H2O 时,配平则是毫无压力,但是若遇到类似Fe36Si5 + H3PO4 + K2CrO7 = FePO4 + SiO2 + K3PO4+ CrPO4 + H2O 这种元素种类繁多,化学计量数复杂的化学方程式,若仅依靠人力去配平可能是一件极为困难的事情。而计算机具有庞大的计算能力,故我们想到编写程序来解决复杂化学方程的配平。本程序将实现化学方程式和离子方程式的配平,并支持检测输入的方程式是否配平。

主要思路:

先做字符串处理,把每个物质的的每种原子数都找出来,

然后利用每种原子的守恒 关于系数 列出方程组 进行求解 (化合价好像不太现实,我化学不好)

先说方程的解法,

解线性方程组当然是要用高斯消元了。

/*
Chemical Equation Balancer
HiJ1m 2017.10.6
*/
#include<bits/stdc++.h>
using namespace std;
inline int gcd(int x,int y){return x%y==0?y:gcd(y,x%y);
}
inline int lcm(int x,int y){return x*y/gcd(x,y);
}
struct frac{                            //分数类 int a,b;void reduce(){int x=gcd(a,b);a/=x,b/=x;};frac operator = (int x){a=x,b=1;return *this;};frac operator = (const frac x){a=x.a,b=x.b;reduce();return *this;};frac operator + (const frac x){return (frac){b*x.a+a*x.b,b*x.b};};frac operator - (const frac x){return (frac){a*x.b-b*x.a,b*x.b};};frac operator * (const frac x){return (frac){a*x.a,b*x.b};};frac operator / (const frac x){return (frac){a*x.b,b*x.a};};bool operator < (const frac x){return a*x.b<b*x.a;};bool operator == (const frac x){return a*x.b==b*x.a;};void print(){if(b==1)printf("%d\n",a);else printf("%d/%d\n",a,b);};
};        
inline frac Abs(frac x){int p=x.a>0?x.a:-x.a,q=x.b>0?x.b:-x.b;return (frac){p,q};
}                                            
char s[55];
int fun[55][55];
int Map[27][27];                        //手动MAP 
frac M[55][55];                            //求解矩阵
frac ans[55];                            //解 
int Ans[55];                            //整数解 
int cnt,c1,c2,flag=1,N,K;                //cnt数元素,c1数反应物,c2总数 (未知数的数量) 
char mat[55][55];                        //存储物质的名称 
void print(){printf("%d %d\n",N,K);for(int i=1;i<=K;i++){for(int j=1;j<=N+1;j++)printf("%d ",M[i][j].a);printf("\n");}printf("\n");
}
inline int getint(int pos){                //读数 pos++;if(s[pos]>='a'&&s[pos]<='z')pos++;if(s[pos]<'0'||s[pos]>'9')return 1;                                //没数就是1 else {int x=0;while(s[pos]>='0'&&s[pos]<='9')x=x*10+s[pos]-'0',pos++;        //读元素后面的数字 return x;}
}
inline void scan(int l,int r){             //处理物质    c2++;for(int i=0;i<=r-l;i++)mat[c2][i]=s[l+i];        //存下元素的名字if(flag==1)c1++;                                //统计一下反应物数量int tmp=1;                                        //tmp是小括号倍数 for(int i=l;i<=r;i++){if(s[i]==')')tmp=1;                                                        if(s[i]=='('){int j=i+1;while(s[j]!=')')j++;            //找这个括号的范围 tmp=getint(j);                            //读")"右边的数字 }if(s[i]>='A'&&s[i]<='Z'){                    //发现元素 int x=s[i]-'A'+1,y=0;if(s[i+1]>='a'&&s[i]<='z')                //看一眼是一个字母的还是两个的 y=s[i+1]-'a'+1;if(!Map[x][y])Map[x][y]=++cnt;            //判重fun[Map[x][y]][c2]+=flag*getint(i)*tmp;    //把这个物质里的这种元素数量放进矩阵里,坐标(map[x][y],c2) }} 
}
inline bool Solve(){                    //解方程  (矩阵 高cnt,宽c2+1,c2+1列常数全0) ans[c2]=1;                                    //令最后一个解为1for(int i=1;i<=cnt;i++){for(int j=1;j<=c2;j++)M[i][j]=fun[i][j];}for(int i=1;i<=cnt;i++)M[i][c2].a=-M[i][c2].a;            //移到常数 //高斯消元过程 N=c2-1,K=cnt;for(int k=1;k<=N;k++){frac maxm=(frac){-1,1};int maxi;for(int i=k;i<=K;i++)if(maxm<Abs(M[i][k]))maxm=Abs(M[i][k]),maxi=i;if(maxm==(frac){0,1})return false;if(maxi!=k)for(int j=1;j<=N+1;j++){swap(M[k][j],M[maxi][j]);}frac tmp=M[k][k];for(int j=1;j<=N+1;j++)M[k][j]=M[k][j]/tmp;for(int i=k-1?1:2;i<=K;i++){if(i==k)continue;frac tmp=M[i][k];for(int j=1;j<=N+1;j++)M[i][j]=M[i][j]-tmp*M[k][j];}}return true;
}
int main()
{
//    printf("Chemical Equation Balancer\n");
//    printf("\nEnter the chemical equation:\n");scanf("%s",s);int lst=0;for(int i=1;i<strlen(s);i++){if(i==strlen(s)-1)scan(lst,i);                    if(s[i]=='+'||s[i]=='=')scan(lst,i-1),lst=i+1;     if(s[i]=='=')flag=-1;                            //等号后面的系数变负 }if(Solve())for(int i=1;i<=c2-1;i++)ans[i]=M[i][N+1];else printf("No Solution");int tmp=lcm(ans[1].b,ans[2].b);for(int i=3;i<=c2;i++)tmp=lcm(tmp,ans[i].b);for(int i=1;i<=c2;i++)Ans[i]=ans[i].a*tmp/ans[i].b;    //取分母Lcm,把分数变整数 for(int i=1;i<=c2;i++){if(Ans[i]>1)printf("%d",Ans[i]);for(int j=0;j<strlen(mat[i]);j++)printf("%c",mat[i][j]);if(i==c2)return 0;else if(i==c1)printf("=");else printf("+");}
}

另一个代码:

/* Exzh Cross Platfrom Toolkit (ECPT) Qt Version* (This file is the part of the ECPT Project)* Author: Exzh_PMGI* E-mail: realexzh@gmail.com* License: LGPL v3.0 / Exzh Commerical License* Copyright: (C) Exzh_PMGI* Qt Framework 5.10 has been tested successfully* If you want to use the code for business,* please contact me by my email.*/#include "exequationbalancer.h"#include <QDebug>int gcd(int x, int y) {return x % y == 0 ? y : gcd(y, x%y);
}int lcm(int x, int y) {return x * y / gcd(x, y);
}frac createFrac(int a, int b)
{frac tmp = { a,b };return tmp;
}frac Abs(frac x) {int p = x.a>0 ? x.a : -x.a, q = x.b>0 ? x.b : -x.b;return createFrac(p, q);
}string exEquationBalancer::getResult(string inputstr)
{strcpy(s,inputstr.c_str());int lst = 0;for (int i = 1;i<strlen(s);i++) {if (i == strlen(s) - 1)scan(lst, i);if (s[i] == '+' || s[i] == '='){scan(lst, i - 1);lst = i + 1;}if (s[i] == '=')flag = -1;                            //等号后面的系数变负}if (Solve())for (int i = 1;i <= c2 - 1;i++)ans[i] = M[i][N + 1];else output+="No Solution";int tmp = lcm(ans[1].b, ans[2].b);for (int i = 3;i <= c2;i++)tmp = lcm(tmp, ans[i].b);for (int i = 1;i <= c2;i++)Ans[i] = ans[i].a*tmp / ans[i].b;    //取分母Lcm,把分数变整数for (int i = 1;i <= c2;i++){if (Ans[i]>1) output+=to_string(Ans[i]);for (int j = 0;j<strlen(mat[i]);j++)output+=mat[i][j];if (i == c2){return output;qDebug()<<QString::fromStdString(output);}else if (i == c1) output+="=";else output+="+";}
}bool exEquationBalancer::Solve() {                    //解方程  (矩阵 高cnt,宽c2+1,c2+1列常数全0)ans[c2] = 1;                                    //令最后一个解为1for (int i = 1;i <= cnt;i++) {for (int j = 1;j <= c2;j++)M[i][j] = fun[i][j];}for (int i = 1;i <= cnt;i++)M[i][c2].a = -M[i][c2].a;            //移到常数//高斯消元过程N = c2 - 1, K = cnt;for (int k = 1;k <= N;k++) {frac maxm = createFrac(-1, 1);int maxi;for (int i = k;i <= K;i++)if (maxm<Abs(M[i][k]))maxm = Abs(M[i][k]), maxi = i;if (maxm == createFrac(0, 1))return false;if (maxi != k)for (int j = 1;j <= N + 1;j++) {swap(M[k][j], M[maxi][j]);}frac tmp = M[k][k];for (int j = 1;j <= N + 1;j++)M[k][j] = M[k][j] / tmp;for (int i = k - 1 ? 1 : 2;i <= K;i++) {if (i == k)continue;frac tmp = M[i][k];for (int j = 1;j <= N + 1;j++)M[i][j] = M[i][j] - tmp * M[k][j];}}return true;
}void exEquationBalancer::scan(int l, int r) {             //处理物质c2++;for (int i = 0;i <= r - l;i++)mat[c2][i] = s[l + i];        //存下元素的名字if (flag == 1)c1++;                                //统计一下反应物数量int tmp = 1;                                        //tmp是小括号倍数for (int i = l;i <= r;i++) {if (s[i] == ')')tmp = 1;if (s[i] == '(') {int j = i + 1;while (s[j] != ')')j++;            //找这个括号的范围tmp = getint(j);                            //读")"右边的数字}if (s[i] >= 'A'&&s[i] <= 'Z') {                    //发现元素int x = s[i] - 'A' + 1, y = 0;if (s[i + 1] >= 'a'&&s[i] <= 'z')                //看一眼是一个字母的还是两个的y = s[i + 1] - 'a' + 1;if (!Map[x][y])Map[x][y] = ++cnt;            //判重fun[Map[x][y]][c2] += flag * getint(i)*tmp;    //把这个物质里的这种元素数量放进矩阵里,坐标(map[x][y],c2)}}
}int exEquationBalancer::getint(int pos) {                //读数pos++;if (s[pos] >= 'a'&&s[pos] <= 'z')pos++;if (s[pos]<'0' || s[pos]>'9')return 1;                                //没数就是1else {int x = 0;while (s[pos] >= '0'&&s[pos] <= '9')x = x * 10 + s[pos] - '0', pos++;        //读元素后面的数字return x;}
}void exEquationBalancer::print() {output += to_string(N);output += " ";output += to_string(K);output += "\n";for (int i = 1;i <= K;i++) {for (int j = 1;j <= N + 1;j++){output += to_string(M[i][j].a);output += " ";}output += "\n";}output += "\n";
}

c++头文件

/* Exzh Cross Platfrom Toolkit (ECPT) Qt Version* (This file is the part of the ECPT Project)* Author: Exzh_PMGI* E-mail: realexzh@gmail.com* License: LGPL v3.0 / Exzh Commerical License* Copyright: (C) Exzh_PMGI* Qt Framework 5.10 has been tested successfully* If you want to use the code for business,* please contact me by my email.*/#ifndef EXEQUATIONBALANCER_H
#define EXEQUATIONBALANCER_H#include <string>
#include "../exstdc++.h"using namespace std;
static string output;
int lcm(int x, int y);
int gcd(int x, int y);struct frac {                            //分数类int a, b;void reduce() {int x = gcd(a, b);a /= x, b /= x;}frac createFrac(int a, int b){frac tmp = { a,b };return tmp;}frac operator = (int x) {a = x, b = 1;return *this;}frac operator = (const frac x) {a = x.a, b = x.b;reduce();return *this;}frac operator + (const frac x) {return createFrac(b*x.a + a * x.b, b*x.b);}frac operator - (const frac x) {return createFrac(a*x.b - b * x.a, b*x.b);}frac operator * (const frac x) {return createFrac(a*x.a, b*x.b);}frac operator / (const frac x) {return createFrac(a*x.b, b*x.a);}bool operator < (const frac x) {return a * x.b<b*x.a;}bool operator == (const frac x) {return a * x.b == b * x.a;}void print() {if (b == 1){output += to_string(a);output += "\n";}else{output += to_string(a);output += "/";output += to_string(b);}}
};frac createFrac(int a, int b);
frac Abs(frac x);class exEquationBalancer
{
public:string getResult(string inputstr);private:bool Solve();void scan(int l, int r);int getint(int pos);void print();char s[55];int fun[55][55];int Map[27][27];                        //手动MAPfrac M[55][55];                            //求解矩阵frac ans[55];                            //解int Ans[55];                            //整数解int cnt, c1, c2, flag = 1, N, K;                //cnt数元素,c1数反应物,c2总数 (未知数的数量)char mat[55][55];                        //存储物质的名称
};#endif // EXEQUATIONBALANCER_H

附录:

怎样用高斯消元 方法/步骤

下面的是咱们要求解的线性方程组,先把四个方程编上序号。

先把第一行乘以1/2,然后把第一行的相应倍数加到第二、三、四行上。

再把第二行乘以-2,接着将其相应的倍数加到第三、四行上,然后把第三行乘以-1/6。

将第三行的二倍加到第四行上,再把第四行乘以3/7。

然后往回代,就是把第四行的相应倍数加到第一、第二、第三行上;把第三行的相应倍数加到第一、第二行上。

再把第二行的相应倍数加到第一行上,最后根据得出的矩阵列出方程组,解得最后的解。

这篇关于C++配平化学方程式,附源码。配平化学方程式的C++代码实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/303163

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python脚本实现自动删除C盘临时文件夹

《Python脚本实现自动删除C盘临时文件夹》在日常使用电脑的过程中,临时文件夹往往会积累大量的无用数据,占用宝贵的磁盘空间,下面我们就来看看Python如何通过脚本实现自动删除C盘临时文件夹吧... 目录一、准备工作二、python脚本编写三、脚本解析四、运行脚本五、案例演示六、注意事项七、总结在日常使用

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

使用Python实现在Word中添加或删除超链接

《使用Python实现在Word中添加或删除超链接》在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能,本文将为大家介绍一下Python如何实现在Word中添加或... 在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能。通过添加超

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一