巨大な数値の計算

投稿者:Material 305033 1 mini cfm_ 投稿日:2016/03/30 16:44

参考にしたサイト
http://7ujm.net/index.html

数値の圧縮などで、大きな数値を計算したい方へ。
#====サンプル====

# 300桁まで計算する
math_setSize(300)

#足し算 =a+b
speak(math_add(3456535300,55515561155))
#引き算 =a-b
speak(math_sub(3003,555656455))
#掛け算 =a*b
speak(math_mul(30644566651666130,55445556661656))
# 除算の商 =floor(a/b)
speak(math_div(304340,23631))
# 剰余 =a%b
speak(math_mod(304340,23631))

#計算結果
#58972096455
#-555653452
#1699105056656848296693084911280
#12
#20768

#====サンプル2====
math_setSize(300)
x=1
n=500
while n>0
 x=math_mul(x,2)
 n=n-1
end
speak(x)
#計算結果
#3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376


最初にmath_setSizeで何桁まで計算するか指定する必要があります。
正確には、奇数を指定した場合+1されます(5を渡すと6が設定される)
正しい答えが123456のとき、6桁以上を指定する必要があります。
基本的には、数をかなり大きくしておけば大丈夫だと思います。

 関数
def cmp(ar,ar1)
 i=getVariable("math_size")-1
 while i>=0
  if ar[i]<ar1[i] then return -1;end
  if ar[i]>ar1[i] then return 1;end
  i=i-1
 end
 return 0
end
def cmp0(ar)
 i=getVariable("math_size")-1
 while i>=0
  if ar[i]<0 then return -1;end
  if ar[i]>0 then return 1;end
  i=i-1
 end
 return 0
end
def floor2(num)
 if num>0 then return floor(num);else return floor(num)+1;end
end
def r_shift(ar)
 ar[0]=ar[0]/10
 i=1
 while i<getVariable("math_size")
  pos=ar[i]
  ar[i-1]=ar[i-1]+((ar[i]%10)*10)
  ar[i]=floor(ar[i]/10)
  i=i+1
 end
end
def l_shift(ar)
 i=getVariable("math_size")-1
 while i>=0
  ar[i+1]=ar[i+1]+floor(ar[i]/10)
  ar[i]=(ar[i]*10)%100
  i=i-1
 end
end
def turn(ar)
 i=0
 while i<getVariable("math_size")
  ar[i]=-ar[i]
  i=i+1
 end
end
def turn2(ar)
 ar2=createArray()
 i=0
 while i<getVariable("math_size")
  ar2[i]=-ar[i]
  i=i+1
 end
 return ar2
end
def d02(num)
 x=toNumber(num)
 if x<10
  return "0"+toString(x)
 else
  return toString(x)
 end
end
def getNumArray(num)
 ar=createArray()
 if num<0 then
  nu=splitString(toString(-num), "")
  len=getArrayLength(nu)
  i=0
  while i<getVariable("math_size")
   if len==i*2+1
    ar[i]=-toNumber(nu[len-i*2-1])
   elsif len>i*2+1
    ar[i]=-toNumber(nu[len-i*2-2])*10-toNumber(nu[len-i*2-1])
   else
    ar[i]=0
   end
   i=i+1
  end
 else
  nu=splitString(toString(num), "")
  len=getArrayLength(nu)
  i=0
  while i<getVariable("math_size")
   if len==i*2+1
    ar[i]=toNumber(nu[len-i*2-1])
   elsif len>i*2+1
    ar[i]=toNumber(nu[len-i*2-2])*10+toNumber(nu[len-i*2-1])
   else
    ar[i]=0
   end
   i=i+1
  end
 end
 return ar
end
def ar_str(ar)
 start_flag=false
 p_flag=cmp0(ar)
 if p_flag==0 then
  return "0"
 else
  if p_flag==-1
   s="-"
   turn(ar)
  else
   s=""
  end
  i=getVariable("math_size")-1
  while i>=0
   if ar[i]!=0 || start_flag
    if !start_flag
     s=s+toString(ar[i])
     start_flag=true
    else
     s=s+toString(d02(ar[i]))
    end
   end
   i=i-1
  end
  if p_flag==-1 then turn(ar);end
  return s
 end
end
def math_setSize(size)
 setVariable("math_size",floor(size/2)+1)
end
#加算
def math_add(a,b)
 ar=getNumArray(a)
 ar2=getNumArray(b)
 ar3=createArray()
 i=0
 while i<getVariable("math_size")
  ar3[i]=ar[i]+ar2[i]
  i=i+1
 end
 i=0
 while i<getVariable("math_size")
  if ar3[i]>99
   ar3[i]=ar3[i]-100
   ar3[i+1]=ar3[i+1]+1
  elsif ar3[i]<-99
   ar3[i]=ar3[i]+100
   ar3[i+1]=ar3[i+1]-1
  end
  i=i+1
 end
 p_flag=cmp0(ar3)
 if p_flag!=0
  i=0
  while i<getVariable("math_size")
   if p_flag>0
    if 0>ar3[i]
     ar3[i+1]=ar3[i+1]-1
     ar3[i]=ar3[i]+100
    end
   else
    if 0<ar3[i]
     ar3[i+1]=ar3[i+1]+1
     ar3[i]=ar3[i]-100
    end
   end
   i=i+1
  end
 end
 return ar_str(ar3)
end
#配列を加算
def math_addAr(ar,ar2)
 ar3=createArray()
 i=0
 while i<getVariable("math_size")
  ar3[i]=ar[i]+ar2[i]
  i=i+1
 end
 i=0
 while i<getVariable("math_size")
  if ar3[i]>99
   ar3[i]=ar3[i]-100
   ar3[i+1]=ar3[i+1]+1
  elsif ar3[i]<-99
   ar3[i]=ar3[i]+100
   ar3[i+1]=ar3[i+1]-1
  end
  i=i+1
 end
 p_flag=cmp0(ar3)
 if p_flag!=0
  i=0
  while i<getVariable("math_size")
   if p_flag>0
    if 0>ar3[i]
     ar3[i+1]=ar3[i+1]-1
     ar3[i]=ar3[i]+100
    end
   else
    if 0<ar3[i]
     ar3[i+1]=ar3[i+1]+1
     ar3[i]=ar3[i]-100
    end
   end
   i=i+1
  end
 end
 return ar3
end
#減算
def math_sub(a,b)
 return math_add(a,-b)
end
#配列を減算
def math_subAr(ar,ar2)
 return math_addAr(ar,turn2(ar2))
end
#乗算
def math_mul(a,b)
 ar=getNumArray(a)
 ar2=getNumArray(b)
 ar3=createArray()
 i=0
 while i<getVariable("math_size")
  ar3[i]=0
  i=i+1
 end
 i=0
 while i<getVariable("math_size")
  if ar2[i]!=0
   j=0
   while j<getVariable("math_size")
    ar3[j+i]=ar3[j+i]+ar[j]*ar2[i]
    #3桁目を繰り上げる
    if ar3[j+i]>99 || ar3[j+i]<-99
     pos=ar3[j+i]/100
     ar3[j+i]=ar3[j+i]%100 #ar3[j+i]-(pos*100)
     ar3[j+1+i]=ar3[j+1+i]+floor2(pos)
    end
    j=j+1
   end
  end
  i=i+1
 end
 return ar_str(ar3)
end
#除算
def math_div(a,b)
 ar=getNumArray(a)
 ar2=getNumArray(b)
 ar3=createArray()
 pos=0
 i=0
 while i<getVariable("math_size")
  ar3[i]=0
  i=i+1
 end
 div_flag=cmp0(ar)# 被除数の符号フラグ
 met_flag=cmp0(ar2)# 法の符号フラグ
 if !div_flag || !met_flag then return 0;end #法、被除数のどちらかが0であるため計算中止
 if -1==div_flag then turn(ar);end #被除数が負数であるため正数にする
 if -1==met_flag then turn(ar2);end #法が負数であるため正数にする
 while cmp(ar,ar2)==1 && floor(ar2[getVariable("math_size")-1]/10)==0
  pos=pos+1
  l_shift(ar2)
 end
 while pos>=0
  if cmp(ar,ar2)>=0
   ar=math_subAr(ar,ar2)
   if (pos%2)!=0 then ar3[pos/2]=ar3[pos/2]+10;else ar3[pos/2]=ar3[pos/2]+1;end
  else
   if pos!=0 then r_shift(ar2);end
   pos=pos-1
  end
 end
 if -1==div_flag then turn(ar);end #被除数の符号を戻す
 if div_flag!=met_flag then turn(ar3);end #被除数と法の符号が違うため、答えをマイナスにする
 return ar_str(ar3)
end
#剰余
def math_mod(a,b)
 ar=getNumArray(a)
 ar2=getNumArray(b)
 pos=0
 div_flag=cmp0(ar)# 被除数の符号フラグ
 met_flag=cmp0(ar2)# 法の符号フラグ
 if !div_flag || !met_flag then return 0;end #法、被除数のどちらかが0であるため計算中止
 if -1==div_flag then turn(ar);end #被除数が負数であるため正数にする
 if -1==met_flag then turn(ar2);end #法が負数であるため正数にする
 while cmp(ar,ar2)==1 && floor(ar2[getVariable("math_size")-1]/10)==0
  pos=pos+1
  l_shift(ar2)
 end
 while pos>=0
  if cmp(ar,ar2)>=0
   ar=math_subAr(ar,ar2)
  else
   if pos!=0 then r_shift(ar2);end
   pos=pos-1
  end
 end
 if -1==div_flag then turn(ar);end #被除数の符号を戻す
 return ar_str(ar)
end


コメントする

コメントするには、ログインする必要があります。

コメント一覧

Cdv30200 aoi icon mini aoihikawa(投稿日:2016/03/30 21:37, 履歴)
関数のボリューム凄いですね、、、(w