『数学ガール (数学ガールシリーズ 1)』のp231では「極限としての関数の姿」と題してsin関数のテイラー展開を扱っています。テイラー展開の無限級数を有限個だけ項を取り出して部分和を求めていくと、sin関数に近付いて行く様子が図を交えて分かりやすく解説されていますが、実際に試してみました。
学習のポイントは、
- Proc
を使ってみるです。gen_taylor関数の中で使ってみました。使い方が正しいか分かりせんが…。
実行結果は、において、テイラー展開を30項まで行ってみました。
次第にsin関数に近付いていく様子を観察することができました。
sin_curve.rb
require 'cairo' class Graph FORMAT = Cairo::FORMAT_ARGB32 attr_reader :x_max, :y_max def initialize(width, height, x_max, y_max) @width = width @height = height @x_max = x_max @y_max = y_max create_graph end def create_graph @surface = Cairo::ImageSurface.new(FORMAT, @width, @height) @context = Cairo::Context.new(@surface) @context.set_source_rgb(1, 1, 1) @context.rectangle(0, 0, @width, @height) @context.fill draw_line(-@x_max, 0, @x_max, 0, [0.2, 0.2, 0.2]) # x軸 draw_line(0, @y_max, 0, -@y_max, [0.2, 0.2, 0.2]) # y軸 end def draw_line(x1, y1, x2, y2, rgb) x1 = x1 * @width /@x_max/2.0 + @width /2.0 y1 = -y1 * @height/@y_max/2.0 + @height/2.0 x2 = x2 * @width /@x_max/2.0 + @width /2.0 y2 = -y2 * @height/@y_max/2.0 + @height/2.0 @context.set_source_rgb(rgb) @context.move_to(x1, y1) @context.line_to(x2, y2) @context.stroke end def write_to_png(file_name) @surface.write_to_png(file_name) end end if __FILE__ == $0 include Math def sin_curve(graph, from, to, step) rgb = [1, 0, 0] x = from xx = x + step while x <= to graph.draw_line(x, sin(x), xx, sin(xx), rgb) x = xx xx += step end end def sin_curve_with_taylor(graph, from, to, step) 1.step(30, 2) do |k| # 30項まで taylor = gen_taylor(k) rgb = [rand, rand, rand] x = from xx = x + step while x <= to graph.draw_line(x, taylor.call(x), xx, taylor.call(xx), rgb) x = xx xx += step end end end # k項までのテイラー展開 def gen_taylor(k) def fact(n) (1..n).inject(1){|p, i| p * i} end return Proc.new do |x| result = 0 sign_flag = 0 1.step(k, 2) do |j| result += ((-1.0)**sign_flag) * (x**j / fact(j)) sign_flag = (sign_flag + 1) % 2 end result end end graph = Graph.new(600, 300, 4*PI, 4) sin_curve_with_taylor(graph, -graph.x_max, graph.x_max, 0.2) sin_curve(graph, -graph.x_max, graph.x_max, 0.2) graph.write_to_png("sin_curve.png") end