[トップ][一覧][最近の更新]

編集履歴:過去のバージョン

2015/09/09 09:47:32 JST時点での数式の文字列を計算するモジュールの内容

現在のバージョンとの差分を見る

編集履歴ページに戻る

  数式の文字列を計算するモジュール
  {{{
  #module mojikeisan
  	//数式の文字列を計算するモジュール(修正版)
  	//使い方 keisan(数式,計算方法[0=整数型,1=実数型,2=簡易数式チェック])
  	//keisan(p1,p2)
  	//p1=strings : 数式
  	//p2=0~2(0)  : 計算方法( 0整数型,1=実数型,2=簡易数式チェック)
  	//整数型の場合返し値は整数型(int)
  	//実数型の場合返し値は実数型(double)
  	//簡易数式チェックの場合 0=数式はおかしい 1=数式は正しい (注意: ()+-*/以外の文字のチェックはしません)
  	//計算方法に0から2以外の数を入れた場合整数型で計算します
  
  	//NYSL 0.9982で公開します
  	//ライセンス文 (http://www.kmonos.net/nysl/)
  
  	#define I tmp.0
  	#define J tmp.1
  	#define K tmp.2
  	#define L tmp.3
  	#define M tmp.4
  	#define N tmp.5
  	#define O tmp.6
  	#define P tmp.7
  	#define Q tmp.8
  	#define R tmp.9
  	#define S tmp.10
  	#define T tmp.11
  
  	#defcfunc keisan str p1 , int atype , local sushiki , local nagasa , local stmp , local tmp , local btype , local dtmp//ローカル変数はつけ外ししてください
  		sushiki=p1
  		nagasa=strlen(sushiki)
  		btype=atype
  		if atype<0 | atype>2 : btype=0
  		if btype==1{
  			ddim dtmp,5
  			sdim stmp,nagasa*8+4,4
  		}else{
  			sdim stmp,nagasa+4,4
  		}
  		dim tmp,12
  		I=0
  		K=0
  		while I<nagasa//数式チェック
  			J=peek(sushiki,I)
  			if J=='(' : K+=1
  			if J==')' : K-=1
  			if I<nagasa-1{
  				if J=='/' & peek(sushiki,I+1)=='0'{
  					K=-1 : _break
  				}
  				if J=='(' | J=='+' | J=='-' | J=='/' | J=='*'{
  					J=peek(sushiki,I+1)
  					if J=='+' | J=='-' | J=='/' | J=='*'{
  						K=-1 : _break
  					}
  					J=peek(sushiki,I)
  				}
  			}
  			if I==0{
  				if J==')' | J=='+' | J=='-' | J=='/' | J=='*'{
  					K=-1 : _break
  				}
  			}
  			if I==nagasa-1{
  				if J=='(' | J=='+' | J=='-' | J=='/' | J=='*'{
  					K=-1 : _break
  				}
  			}
  			I++
  		wend
  
  		if K!=0 : return 0//かっこの数が合わない場合
  		if btype==2 : return 1
  
  		while//計算
  
  			if peek(sushiki,0)=='-' | peek(sushiki,0)==0 : _break
  
  			//かっこの中身を取り出し
  			I=0
  			J=instr(sushiki,I,"(") 
  			while J!=-1 & J<instr(sushiki,I,")")
  				I+=(J+1)
  				J=instr(sushiki,I,"(") 
  			wend
  			J=instr(sushiki,I,")")
  			if J==-1 : J=strlen(sushiki)-I
  
  			poke stmp.0,J,0
  			memcpy stmp.0,sushiki,J,,I
  
  			if J+I<nagasa {
  				poke stmp.1,nagasa-(J+I+1),0
  				memcpy stmp.1,sushiki,nagasa-(J+I+1),,J+I+1
  			}else{
  				poke stmp.1,0,0
  			}
  
  			if I>0 : poke sushiki,I-1,0 : else : poke sushiki,0,0
  
  			//中身を計算
  			T=J
  			while instr(stmp.0,0,"*")!=-1 | instr(stmp.0,0,"/")!=-1//掛け算と割り算を先に計算
  				//前から計算
  				K=0
  				L=0
  				while L!=-1
  					K+=(L+1)
  					L=instr(stmp.0,K,"+")
  					M=instr(stmp.0,K,"/")
  					N=instr(stmp.0,K,"*")
  					if N==-1 : N=J
  					if M==-1 : M=J
  					if L==-1 | L>N | L>M : L=instr(stmp.0,K,"-")
  					if L==-1 | L>N | L>M : L=-1
  				wend
  				if K==1 : K=0
  				L=instr(stmp.0,K,"/")
  				M=instr(stmp.0,K,"*")
  				if M==-1 : M=J-K
  				if L>M | L==-1 : L=M
  				if L==-1 : L=J-K
  
  				poke stmp.2,L,0
  				memcpy stmp.2,stmp.0,L,,K
  				if btype==0 : O=int(stmp.2)
  				if btype==1 : dtmp.0=double(stmp.2)
  
  				M=instr(stmp.0,K+L,"+")
  				S=instr(stmp.0,K+L+1,"*")+1
  				R=instr(stmp.0,K+L+1,"/")+1
  				T=instr(stmp.0,K+L,"-")
  				if S==0 : S=J-(K+L)
  				if R==0 : R=J-(K+L)
  				if T==-1 : T=J-(K+L)
  
  				if M==-1 | M>T : M=T
  				if M==-1 | M>S : M=S
  				if M==-1 | M>R : M=R
  				if M==-1:M=J-(K+L)
  
  				poke stmp.2,M-1,0
  				memcpy stmp.2,stmp.0,M-1,,K+L+1
  				if btype==0 : P=int(stmp.2)
  				if btype==1 : dtmp.1=double(stmp.2)
  
  				if btype==0{
  					if peek(stmp.0,K+L)=='*' : O*=P
  					if peek(stmp.0,K+L)=='/' {
  						if P==0 : K=-1 : _break
  						O/=P
  					}
  				}
  				if btype==1{
  					if peek(stmp.0,K+L)=='*' : dtmp.0*=dtmp.1
  					if peek(stmp.0,K+L)=='/' : dtmp.0/=dtmp.1
  				}
  	
  				poke stmp.3,J-(M+K+L)
  				memcpy stmp.3,stmp.0,J-(M+K+L),,M+K+L
  
  				poke stmp.0,K,0
  				if btype==0 : stmp.0+=str(O)+stmp.3
  				if btype==1 : stmp.0+=str(dtmp.0)+stmp.3
  				J=strlen(stmp.0)
  			wend
  			if K==-1 : sushiki="0" : _break
  
  			if instr(stmp.0,0,"+")==-1 & instr(stmp.0,0,"-")==-1{
  				poke stmp.0,J,"+0"
  				J+=2
  				poke stmp.0,J,0
  			}
  
  			while instr(stmp.0,0,"+")!=-1 | instr(stmp.0,0,"-")!=-1//足し算と引き算を後に計算
  				//後ろから計算
  				K=-1
  				L=0
  				while L!=-1
  					K+=(L+1)
  					L=instr(stmp.0,K,"+")
  					N=instr(stmp.0,K,"-")
  					if N==-1 : N=J
  					if L==-1 | L>N : L=N
  					if L==J : L=-1
  				wend
  
  				if K==1 : K=0
  				L=instr(stmp.0,K,"+")
  				M=instr(stmp.0,K,"-")
  				if M==-1 : M=J-K
  				if L>M | L==-1 : L=M
  				if L==-1 : L=J-K
  
  				poke stmp.2,L,0
  				memcpy stmp.2,stmp.0,L,,K
  
  				if btype==1 : dtmp.0=double(stmp.2)
  				if btype==0 : O=int(stmp.2)
  
  
  				M=0
  				S=-1
  				N=0
  				while N!=-1
  					S+=(N+1)
  					N=instr(stmp.0,S,"+")
  					Q=instr(stmp.0,S,"-")
  					if Q==-1 : Q=K-1
  					if N==-1 | N>Q : N=Q
  					if N==K-1 : _break
  					//N=R
  					M=S
  				wend
  
  				if N+M>=nagasa+4: N=nagasa+3-M//追加
  
  				poke stmp.2,N,0
  
  				memcpy stmp.2,stmp.0,N,,M
  
  				if btype==1 : dtmp.1=double(stmp.2)
  				if btype==0 : P=int(stmp.2)
  
  				if btype==0{
  					if M>0 : if peek(stmp.0,M-1)=='-' : P=-P
  					if peek(stmp.0,K-1)=='+' : Q=P+O
  					if peek(stmp.0,K-1)=='-' : Q=P-O
  				}
  				if btype==1{
  					if M>0 : if peek(stmp.0,M-1)=='-' : dtmp.1=-dtmp.1
  					if peek(stmp.0,K-1)=='+' : dtmp.2=dtmp.1+dtmp.0
  					if peek(stmp.0,K-1)=='-' : dtmp.2=dtmp.1-dtmp.0
  				}
  
  
  				poke stmp.3,J-(K+L),0
  				memcpy stmp.3,stmp.0,J-(K+L),,K+L
  
  				if btype==0{
  					if Q>0 {
  						poke stmp.0,M,0
  					}else{
  						if M>0 : poke stmp.0,M-1,0 : else : poke stmp.0,0,0
  					}
  					stmp.0+=str(Q)+stmp.3
  				}
  				if btype==1{
  					if dtmp.2>0 {
  						poke stmp.0,M,0
  					}else{
  						if M>0 : poke stmp.0,M-1,0 : else : poke stmp.0,0,0
  					}
  					stmp.0+=str(dtmp.2)+stmp.3
  				}
  				J=strlen(stmp.0)
  
  				J=strlen(stmp.0)
  				if peek(stmp.0,0)=='-'{
  					if I>1 {
  						if peek(sushiki,I-2)=='+'{
  							poke sushiki,I-2,0
  							I--
  							nagasa=(nagasa-(T+I+1))+(J)+(I-1)
  							memcpy sushiki,stmp.0,J,I-1
  							if peek(stmp.1,0)!=0 {
  								memcpy sushiki,stmp.1,(nagasa-(T+I+1)),(J)+(I-1)
  							}else{
  								nagasa=(J)+(I-1)
  							}
  						}else{
  							if peek(sushiki,I-2)=='-'{
  								poke sushiki,I-2,0
  								I--
  								nagasa=(nagasa-(T+I+1))+(J)+(I-1)
  								memcpy sushiki,stmp.0,J,I-1
  								poke sushiki,I-1,'+'
  								if peek(stmp.1,0)!=0 {
  									memcpy sushiki,stmp.1,(nagasa-(T+I+1)),(J)+(I-1)
  								}else{
  									nagasa=(J)+(I-1)
  								}
  							}
  						}
  					}else{
  						nagasa=(nagasa-(T+I+1))+(J)
  						memcpy sushiki,stmp.0,J
  						if peek(stmp.1,0)!=0{
  							memcpy sushiki,stmp.1,(nagasa-(T+I+1)),J
  						}else{
  							nagasa=J
  						}
  					}
  					poke sushiki,nagasa,0
  					_break
  				}
  				if instr(stmp.0,0,"+")==-1 & instr(stmp.0,0,"-")==-1{
  					R=nagasa
  					if I>0 : I--
  					nagasa=(nagasa-(T+I+1))+J+I
  					memcpy sushiki,stmp.0,J,I
  					if peek(stmp.1,0)!=0{
  						memcpy sushiki,stmp.1,(R-(T+I+1)),J+I
  					}else{
  						nagasa=J+I
  					}
  					poke sushiki,nagasa,0
  					_break
  				}
  			wend
  
  			if peek(sushiki,0)==0 {
  				memcpy sushiki,stmp.0,J : nagasa=J
  				if peek(stmp.1,0)!=0{
  					memcpy sushiki,stmp.1,(nagasa-(T+I+1)),J
  					nagasa+=(nagasa-(T+I+1))
  				}
  				poke sushiki,nagasa,0
  			}
  
  			if instr(sushiki,0,"(")==-1 & instr(sushiki,0,")")==-1{
  				if instr(sushiki,0,"+")==-1 & instr(sushiki,0,"-")==-1{
  					if instr(sushiki,0,"*")==-1 & instr(sushiki,0,"/")==-1{
  						_break
  					}
  				}
  			}
  		wend
  		if btype==0 : return int(sushiki)
  		if btype==1 : return double(sushiki)
  
  #global
  
  //サンプル(数字は適当)
  a=keisan("1000+10+(1+(1-42/21+6*1*3/2-820))")+1
  mes a
  mes keisan("")
  mes keisan("4+5*2-1/2")//掛け算割り算は優先
  mes keisan("17+0")
  mes keisan("(7+1)")
  mes keisan("1+(4)")
  mes keisan("((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((45))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))+1")//100重かっこ
  mes keisan(")+3")//エラー処理
  mes keisan("12+3(",2)//エラーチェック
  mes keisan("1+6",2)//エラーチェック
  mes keisan("1+7",6)//エラーチェック
  mes keisan("1/3",1)//実数計算
  mes keisan("1-(1-2)",1)
  mes keisan("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")
  mes keisan("1234567890123456789012345678901234567890123456789012345678901")
  mes keisan("1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1",1)+1
  mes 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1
  mes keisan("5/0")
  mes keisan("5/(4-4)+1")
  mes keisan("5*(7-7)+1")
  }}}
  [https://aa38020e42f53ca54e166915354734af1f102cbd.googledrive.com/host/0B9vewWZYDiXefmNjRWZCb1FrUmpab3o2dk5nTXRkRFdGTXFqTWZjNExVTm41OHUwWFdRUG8/apps/calculat.txt ダウンロード先(外部リンク)]