11/15 第6回 アルゴリズムと計算量


前回までの補足


10/25の課題について


スライドの補足

スライドに使われたプログラム

桁落ち誤差の例

def f(x)
  return Math.log(x);   # f(x)=ln(x)
end

x=1.0;
15.times { |i|
  h =0.1**i #h=0.1, 0.01, ..., 1e-15
  df=(f(x+h)-f(x))/h
  err=(df-1.0).abs;
  print "h=",h,"\t f'(",x,")=",df," err=",err,"\n"
}

情報落ち誤差の例

7.times{ |m| 
   n=10**m                    # n=1,10,100, ..., 1000000
   sum=0.0
   d=1.0/n
   n.times{ sum+=d }
   print "n=",n,"\t d=",d,"\t sum=",sum,"\n"
}

Runge-Kutta方の例(続き)

h=0.1    #時間変数tの差分
t=0       # 時間変数の初期値
u=[1,0,0,1] # 配列uで4変数u0,u1,u2,u3を定義(初期条件を代入)                  

100.times{  #計算のステップを100回繰り返す
  u=rk(t,u,h,&func)  #Runge-Kutta法の計算を1ステップ分行う
  t+=h  #時間変数をhだけ増加させる
  print "t= ", t0, " u[0]= ",u[0]," u[1]= ",u[1]," u[2]= ",u[2]," u[3]= ",u[3]," \n"
}

func=lambda {|t,u|
  new_u=[0,0,0,0]
  r=(u[0]**2+u[1]**2)**1.5
  new_u[0]=u[2];
  new_u[1]=u[3];
  new_u[2]=-u[0]/r;
  new_u[3]=-u[1]/r;
  return new_u
}
def rk(t,u,h,&f)
  k1=muladd([[f.call(t,u),h]])
  k2=muladd([[f.call(t+h/2.0,muladd([[u,1.0],[k1,1.0/2.0]])),h]])
  k3=muladd([[f.call(t+h/2.0,muladd([[u,1],[k2,1.0/2.0]])),h]])
  k4=muladd([[f.call(t+h,muladd([[u,1.0],[k3,1.0]])),h]])
  new_u=muladd([[u,1],[k1,1.0/6.0],[k2,1.0/3.0],[k3,1.0/3.0],[k4,1.0/6.0]])
  return new_u
end

def muladd(pairs)
  r=Array.new(pairs.first.first)
  r.fill(0)
  pairs.each{|a,k| r.size.times{|i| r[i]+=k*a[i]}}
  return r
end