#/*********************************************************** # complex.rb -- 複素数 #***********************************************************/ class Complex def initialize(re, im) @re = re @im = im end attr_accessor :re, :im def to_s # 複素数 $z = x + iy$ を文字列に変換 sprintf("%g%+gi", @re, @im) end def conj # 共役複素数 $\overlinezend$ Complex.new(@re, -@im) end def abs # 絶対値 $|self|$ if (@re == 0); return @im.abs; end if (@im == 0); return @re.abs; end if (@im.abs > @re.abs) t = @re / @im return @im.abs * Math::sqrt(1 + t * t) else t = @im / @re return @re.abs * Math::sqrt(1 + t * t) end end def arg # 偏角 ($-\pi \le \varphi \le \pi$) atan2(@im, @re) end def +(other) # 和 $x + y$ Complex.new(@re + other.re, @im + other.im) end def -(other) # 差 $x - y$ Complex.new(@re - other.re, @im - other.im) end def *(other) # 積 $xy$ Complex.new(@re * other.re - @im * other.im, @re * other.im + @im * other.re) end =begin def /(other) # 商 $x / y$ (単純版) r2 = other.re * other.re + other.im * other.im re = (@re * other.re + @im * other.im) / r2.to_f im = (@im * other.re - @re * other.im) / r2.to_f Complex.new(re, im) end =end def /(other) # 商 $x / y$ (上位桁あふれ対策版) if (other.re.abs >= other.im.abs) w = other.im / other.re.to_f; d = other.re + other.im * w re = (@re + @im * w) / d.to_f im = (@im - @re * w) / d.to_f else w = other.re / other.im.to_f; d = other.re * w + other.im re = (@re * w + @im) / d.to_f im = (@im * w - @re) / d.to_f end Complex.new(re, im) end def Complex.exp(x) # 指数関数 $e^x$ a = Math::exp(x.re) re = a * Math::cos(x.im) im = a * Math::sin(x.im) Complex.new(re, im) end def Complex.log(x) # 自然対数 $\log_e x$ re = 0.5 * Math::log(x.re * x.re + x.im * x.im) im = Math::atan2(x.im, x.re) Complex.new(re, im) end def **(other) # 累乗 $x^y$ Complex.exp(other * Complex.log(self)) end def Complex.sin(x) # 正弦 $\sin x$ e = Math::exp(x.im); f = 1 / e.to_f im = 0.5 * Math::cos(x.re) * (e - f) re = 0.5 * Math::sin(x.re) * (e + f) Complex.new(re, im) end def Complex.cos(x) # 余弦 $\cos x$ e = Math::exp(x.im); f = 1 / e.to_f im = 0.5 * Math::sin(x.re) * (f - e) re = 0.5 * Math::cos(x.re) * (f + e) Complex.new(re, im) end def Complex.tan(x) # 正接 $\tan x$ e = Math::exp(2 * x.im); f = 1 / e.to_f d = Math::cos(2 * x.re) + 0.5 * (e + f) re = Math::sin(2 * x.re) / d.to_f im = 0.5 * (e - f) / d.to_f Complex.new(re, im) end def Complex.sinh(x) # 双曲線正弦 $\sinh x$ e = Math::exp(x.re); f = 1 / e re = 0.5 * (e - f) * Math::cos(x.im) im = 0.5 * (e + f) * Math::sin(x.im) Complex.new(re, im) end def Complex.cosh(x) # 双曲線余弦 $\cosh x$ e = Math::exp(x.re); f = 1 / e.to_f re = 0.5 * (e + f) * Math::cos(x.im) im = 0.5 * (e - f) * Math::sin(x.im) Complex.new(re, im) end def Complex.tanh(x) # 双曲線正接 $\tanh x$ e = Math::exp(2 * x.re); f = 1 / e.to_f d = 0.5 * (e + f) + Math::cos(2 * x.im) re = 0.5 * (e - f) / d.to_f im = Math::sin(2 * x.im) / d.to_f Complex.new(re, im) end SQRT05 = 0.707106781186547524 def Complex.sqrt(x) # 平方根 $\sqrtxend$ r = x.abs w = Math::sqrt(r + x.re.abs) if (x.re >= 0) re = SQRT05 * w im = SQRT05 * x.im / w.to_f else re = SQRT05 * x.im.abs / w.to_f im = (x.im >= 0) ? SQRT05 * w : -SQRT05 * w end Complex.new(re, im) end end def c_conv(x, y) # $x$, $y$ を複素数 $z = x + iy$ に変換 Complex.new(x, y) end printf("x, y ? "); x, y = gets.scan(/[+-.\de]+/).collect{|x| x.to_f} z = c_conv(x, y) printf("z = %s\n", z.to_s) z = Complex.exp(z) printf("exp(z) = %s\n", z.to_s) z = Complex.log(z) printf("log(exp(z)) = %s\n", z.to_s) printf("sqrt(z) * sqrt(z) = %s\n", Complex.sqrt(z) * Complex.sqrt(z)) exit 0