matlab 化学方程式配平
function balanceEquation
%使用实例:
%=========================================
%反应物:Mg(HCO3)2,Ca(OH)2
%生成物:CaCO3,H2O,MgCO3
%配平:Ca(OH)2+Mg(HCO3)2==CaCO3+2H2O+MgCO3
global beFig
global reactantLabel reactantEditfield
global productLabel productEditfield
global reactionButton beLabel
global resultEditfield
beFig=uifigure('units','pixels',...
'position',[10 400 400 210],...
'Numbertitle','off',...
'menubar','none',...
'resize','off',...
'name','化学方程式配平器',...
'color',[1,1,1].*0.98);
reactantLabel=uilabel(beFig,'Text',' 反应物','HorizontalAlignment','left',...
'BackgroundColor',[0,0.49,0.76],'FontColor',[1 1 1],'FontWeight','bold','Position',[10,170,140+230,30],'FontSize',13);
reactantEditfield=uieditfield(beFig,'Value','','Position',[10+52,170,95+230,30]);
productLabel=uilabel(beFig,'Text',' 生成物','HorizontalAlignment','left',...
'BackgroundColor',[0,0.49,0.76],'FontColor',[1 1 1],'FontWeight','bold','Position',[10,130,140+230,30],'FontSize',13);
productEditfield=uieditfield(beFig,'Value','','Position',[10+52,130,95+230,30]);
reactionButton=uibutton(beFig,'Text','配平方程式','BackgroundColor',[0.31 0.58 0.80],'FontColor',[1 1 1],...
'FontWeight','bold','Position',[10,70,95,30],'FontSize',13,'ButtonPushedFcn',@reactionFcn);
beLabel=uilabel(beFig,'Text',' 使用“,”或“;”隔开反应物及生成物,配平结果如下','HorizontalAlignment','left',...
'BackgroundColor',[0.95 0.95 0.95],'Position',[110,70,280,30],'FontSize',12.5,'FontColor',[0.35 0.35 0.35],'FontWeight','bold');
resultEditfield=uieditfield(beFig,'Value','','Position',[10,10,140+240,50],'Editable','off');
%reactionFcn:调用主函数,替换结果展示框信息
function reactionFcn(~,~)
reactant=reactantEditfield.Value;
product=productEditfield.Value;
result=mainFcn(reactant,product);
resultEditfield.Value=result;
end
%mainFcn:主函数,将各处理函数结合,并调用MATLAB整数规划功能
function result=mainFcn(reactant,product)
if ~(isempty(reactant)||isempty(product))
elementList=elementDetection([reactant,product]);
materialSet_r=materialDection(reactant);
materialSet_p=materialDection(product);
timesMat_r=getTimesMat(elementList,materialSet_r);
timesMat_p=getTimesMat(elementList,materialSet_p);
if ~(any(~sum(timesMat_r,2))||any(~sum(timesMat_p,2)))
timesMat=[timesMat_r,-timesMat_p];
f=ones(1,size(timesMat,2));
ic=1:size(timesMat,2);
A=[timesMat;-timesMat];
b=zeros(size(timesMat,1)*2,1);
lb=ones(size(timesMat,2),1);
[x,~,~]=intlinprog(f,ic,A,b,[],[],lb,[]);
result='';
for ir=1:length(materialSet_r)
if round(x(ir))~=1
result=[result,num2str(x(ir))];
end
result=[result,materialSet_r{ir},'+'];
end
result(end)=[];
result=[result,'=='];
for ip=1:length(materialSet_p)
if round(x(ip+length(materialSet_r)))~=1
result=[result,num2str(x(ip+length(materialSet_r)))];
end
result=[result,materialSet_p{ip},'+'];
end
result(end)=[];
else
result='物质不会凭空出现或消失';
end
else
result='物质不会凭空出现或消失';
end
end
%getTimesMat:主函数,获取各种物质的各种元素出现次数
function timesMat=getTimesMat(elementList,materialSet)
timesMat=zeros(length(elementList),length(materialSet));
for i=1:length(elementList)
for j=1:length(materialSet)
timesMat(i,j)=elementOccurrence(materialSet{j},elementList{i});
end
end
end
%elementOccurrence:计算反应物生成物总共含有哪些元素
function times=elementOccurrence(string,element)
elementPos=regexp(string,element);
elementPos=elementPos+length(element)-1;
lowerPos=string~=upper(string);
for i=length(elementPos):-1:1
if elementPos(i)~=length(string)&&lowerPos(elementPos(i)+1)
elementPos(i)=[];
end
end
numberPos=string<=57&string>=48;
earSet_L=string=='('|string=='(';
earSet_R=string==')'|string==')';
earSet_LL=string=='['|string=='[';
earSet_RR=string==']'|string==']';
times=0;
for i=elementPos
timesLayer1=1;timesLayer2=1;timesLayer3=1;
if (i~=length(string))&&numberPos(i+1)
notNumberPos=find([~numberPos,1]);
notNumberPos=notNumberPos(notNumberPos>i);
notNumberPos=notNumberPos(1);
timesLayer1=str2num(string(i+1:notNumberPos-1));
end
earLPos=find(earSet_L);
earRPos=find(earSet_R);
earLPos(earLPos>i)=[];
earRPos(earRPos<i)=[];
if (~isempty(earLPos))&&(~isempty(earRPos))&&(~isempty(earLPos(end)))&&(~isempty(earRPos(1)))
j=earRPos(1);
if (j~=length(string))&&numberPos(j+1)
notNumberPos=find([~numberPos,1]);
notNumberPos=notNumberPos(notNumberPos>j);
notNumberPos=notNumberPos(1);
timesLayer2=str2num(string(j+1:notNumberPos-1));
end
end
earLLPos=find(earSet_LL);
earRRPos=find(earSet_RR);
earLLPos(earLLPos>i)=[];
earRRPos(earRRPos<i)=[];
if (~isempty(earLLPos))&&(~isempty(earRRPos))&&(~isempty(earLLPos(end)))&&(~isempty(earRRPos(1)))
k=earRRPos(1);
if (k~=length(string))&&numberPos(k+1)
notNumberPos=find([~numberPos,1]);
notNumberPos=notNumberPos(notNumberPos>k);
notNumberPos=notNumberPos(1);
timesLayer3=str2num(string(k+1:notNumberPos-1));
end
end
tempNum=timesLayer1*timesLayer2*timesLayer3;
times=times+tempNum;
end
end
%materialDection:将反应物或生成物分割
function materialSet=materialDection(string)
strtrim(string);
sep=string==' '|string==','|string==';'|string=='·'|string=='、'|string==','|string==';';
deletePos=[0 diff(sep)]==0&sep;
string(deletePos)=[];
sep(deletePos)=[];
materialSet(sum(sep)+1)={[]};
sepPos=[-1,find(sep)-1,length(string)];
for i=2:length(sepPos)
tempStr=string(sepPos(i-1)+2:sepPos(i));
tempIndex=find(~(tempStr<=57&tempStr>=48));
tempIndex=tempIndex(1);
tempStr(1:tempIndex-1)=[];
materialSet(i-1)={tempStr};
end
materialSet=unique(materialSet);
end
function elementSet=elementDetection(string)
CHAR.upper=string~=lower(string);
CHAR.notLetter=string==lower(string)&string==upper(string);
elementSet(sum(CHAR.upper))={[]};
for i=find(CHAR.upper)
endingIndexs=find([CHAR.notLetter|CHAR.upper,1]);
endingIndexs=endingIndexs(endingIndexs>i);
endingIndexs=endingIndexs(1);
elementStr=string(i:endingIndexs-1);
elementSet(sum(CHAR.upper(1:i)))={elementStr};
end
elementSet=unique(elementSet);
end
end