Newton法による非線形方程式(f(x)=0)の解

############################################
# ニュートン法
# (exp(x)-3.0*x=0の根)
#      coded by Y.Suganuma
############################################

############################################
# Newton法による非線形方程式(f(x)=0)の解
#      x0 : 初期値
#      eps1 : 終了条件1(|x(k+1)-x(k)|<eps1)
#      eps2 : 終了条件2(|f(x(k))|<eps2)
#      max : 最大試行回数
#      ind : 実際の試行回数
#            (負の時は解を得ることができなかった)
#      fn : f(x)とその微分を計算する関数名
#      return : 解
#      coded by Y.Suganuma
############################################
def newton(x0, eps1, eps2, max, ind, &fn) 

	x1     = x0
	x      = x1
	ind[0] = 0
	sw     = 0

	while sw == 0 and ind[0] >= 0 

		sw      = 1
		ind[0] += 1
		g       = fn.call(0, x1)

		if g.abs() > eps2 
			if ind[0] <= max 
				dg = fn.call(1, x1)
				if dg.abs() > eps2 
					x = x1 - g / dg
					if (x-x1).abs() > eps1 && (x-x1).abs() > eps1*x.abs() 
						x1 = x
						sw = 0
					end
				else 
					ind[0] = -1
				end
			else 
				ind[0] = -1
			end
		end
	end

	return x
end

#################################
# 関数値(f(x))とその微分の計算
#################################
snx = Proc.new { |sw, x|
	if sw == 0
		Math.exp(x) - 3.0 * x
	else
		Math.exp(x) - 3.0
	end
}

			# データの設定
ind  = [0]
eps1 = 1.0e-7
eps2 = 1.0e-10
max  = 20
x0   = 0.0
			# 実行と結果
x = newton(x0, eps1, eps2, max, ind, &snx)

print("ind=", ind[0], "  x=", x, "  f=", snx.call(0,x), "  df=", snx.call(1,x), "\n")