matlab 化学方程式配平

时间:2025-02-08 20:04:52
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