C++实现化学方程式配平
0 引言
化学方程式是化学反应简明的表达形式,它从“质”和“量”两个方面表达了化学反应的意义。故化学方程式的书写是我们学习化学的过程中不可或缺的一个重要环节。当我们遇到简单的化学方程式例如:2H2 + O2 = 2H2O 时,配平则是毫无压力,但是若遇到类似Fe36Si5 + H3PO4 + K2CrO7 = FePO4 + SiO2 + K3PO4+ CrPO4 + H2O 这种元素种类繁多,化学计量数复杂的化学方程式,若仅依靠人力去配平可能是一件极为困难的事情。而计算机具有庞大的计算能力,故我们想到编写程序来解决复杂化学方程的配平。本程序将实现化学方程式和离子方程式的配平,并支持检测输入的方程式是否配平。
1.1 设计思路
对于我们来说,配平化学方程式主要利用元素守恒、化合价升降。而对于每一个化合物,其中元素的化合价都不尽相同,缺少一个标准,并且当我们自己去判断化合价时,也常会出现错误,故计算机难以利用化合价去配平方程式,所以元素守恒对于计算机是最佳的选择。而元素守恒配平方程式其本质就是解线性方程组,故我们只需将配平化学方程式转化成求n元线性方程组的解即可。
首先我们需要知道化学方程式中有哪几种元素,并按ASCII码由上到下升序 排成一列,再读取每个反应物(生成物)中拥有每个元素的个数,最终形成一个元素矩阵 。
其次,便是求解方程组。我们知道,求解n元线性方程组无非就是消元,先得到只含一个未知数的方程,再通过上述求解出的未知数逐步解出剩下的未知数。但是该方法存在一个问题,就是会有浮点数出现,而浮点数在计算机存储时会出现浮点错误 ,故我们需要避开浮点数。这里便用到解n元线性方程的另一种方法——克莱姆法则1 。但是使用克莱姆法则必须满足n个方程对应n个未知数,若未知数的个数比方程组的个数多1,我们便可以使用待定系数法,设其中一个未知数为1,达到减少未知数的效果;若是未知数的个数小于方程组的个数,我们便需要考虑这些多出来的方程组是否存在重复的,若无重复,则去掉多余的方程组仍然能求解出来;若存在重复,则需要进行去重 ,再去求解方程组;若未知数的个数比方程组的个数多2及以上,则该方程组有无穷组解,即无法配平。虽然克莱姆法则求出的解也是分数形式,但观察这些分数形式,不难得出这些分数的分母均为D,所以我们只需提前给所有解都乘上D,以防止分数的出现,再对结果进行约分即可。
接下来我们要处理的是如何将这些系数正确地输出,在化学方程式中,若某个反应物(生成物)前面的化学计量数为1的话,则可以省略不写。故我们需要判断计算出的值是否为1,若为1则不输出,反之输出。
最后,我们输出的反应物(生成物)的位置存在三种情况:1、等号左边 2、化学方程式的末尾 3、除1,2以外的情况。我们需要分别对上述三种情况进行不同的输出,若为情况1,则输出“反应物”+ “=”;若为情况2,则输出“生成物”;若为情况3,则输出“生成物(反应物)”+“+”。
1.2 程序功能介绍
该程序根据巴科斯范式2将化学方程式键入进计算机,若输入方程已配平,则程序会输出“已配平!”:
若未配平且输入正确,则会输出已配平的方程式并以空格隔开:
若方程式错误或无法求解,则会输出“ERROR: 无法求解!”:
按钮功能如下:
① :点击青蒿素的结构简式程序将自动清空输入、输出框的所有内容。
② :最小化窗口。
③ :弹出help窗口,如图
④ :关闭窗口,若 H e l p Help Help窗口此时处于打开状态,则会一并关闭。
⑤ :输入框。
⑥ :输出框。
1.3 例子
我们以下列方程式为例:KMnO4 + HCl = KCl + MnCl2 + Cl2 + H2O,归边写成KMnO4 + HCl - KCl - MnCl2 - Cl2 = H2O,接下来得到元素矩阵:
KMnO4 | HCl | KCl | MnCl2 | Cl2 | H2O | |
---|---|---|---|---|---|---|
K | 1 | 0 | 1 | 0 | 0 | 0 |
Mn | 1 | 0 | 0 | -1 | 0 | 0 |
O | 4 | 0 | 0 | 0 | 0 | 1 |
H | 0 | 1 | 0 | 0 | 0 | 2 |
Cl | 0 | 1 | -1 | -2 | -2 | 0 |
然后通过待定系数使最后一列的系数为1,并利用高斯消元对行列式进行去重,得到矩阵如下:
再利用克莱姆法则计算出上述方程的解,再经过通分、约分得到最简整数解,最终完成配平方程式。
1.4 程序原理(流程图)
2 结论
本程序可以支持绝大多数的化学、离子方程配平和检测是否配平,其算法效率较高,并且通过我们的不断 D e b u g Debug Debug使该程序趋于完善。但是仍存在一个问题,也是所有矩阵法配平的通病,就是对于(元素种类数-反应物数-生成物数)大于 2 2 2的方程式是无法求解的,用方程表示就是(未知数个数-方程组个数)大于 2 2 2,显然这样的方程有无穷多组解,对应化学方程式便是无法求出其具体系数。这个问题的本质是没有结合元素化合价升降去配平,导致条件不足,无法求出方程组的唯一解。
3 核心源代码
/*
* Author:AMT
* Date:2022.