虚数は作れる!swift で学ぶ複素数

58

Upload: taketo-sano

Post on 28-Nov-2014

15.863 views

Category:

Software


6 download

DESCRIPTION

 

TRANSCRIPT

Page 1: 虚数は作れる!Swift で学ぶ複素数
Page 2: 虚数は作れる!Swift で学ぶ複素数

i2 = �1

Page 3: 虚数は作れる!Swift で学ぶ複素数

学校で習うとき1. 虚数単位 i = √-1 がいきなり出てくる

2. 複素数 z = a + bi の四則演算が定義される

3. 「数」と思っていた z がベクトルになってる

4. 「i をかけるのは90度回転です」などと教わる

5. 以後当たり前のように電流や波の方程式に出てくる

i =p�1

z = a+ bi

z

i

Page 4: 虚数は作れる!Swift で学ぶ複素数

ちょっと待ってくれ… i は「想像上の数」なんだろ…?i

Page 5: 虚数は作れる!Swift で学ぶ複素数

そんな長年のモヤモヤを今日は全て解消します!

Page 6: 虚数は作れる!Swift で学ぶ複素数

方針

1. 複素数を最初から2次元ベクトルとして定義する。

2. i^2 = -1 となるように 掛け算を入れる。

3. これが実数を拡大した「数」になることを確認。

→ 虚数単位 i の「実在を信じる」ことを一切求めない!

i2 = �1

i

Page 7: 虚数は作れる!Swift で学ぶ複素数

で。

Page 8: 虚数は作れる!Swift で学ぶ複素数

1. 複素数を作る

Page 9: 虚数は作れる!Swift で学ぶ複素数

まず2次元ベクトルから出発

struct Complex { let x: Double let y: Double init(_ x: Double, _ y: Double) { self.x = x self.y = y } }

Page 10: 虚数は作れる!Swift で学ぶ複素数

let z = Complex(2, 3)

x

y

2

z =

✓23

◆3

Page 11: 虚数は作れる!Swift で学ぶ複素数

イコールを定義

struct Complex: Equatable { … } !func == (a: Complex, b: Complex) -> Bool { return (a.x == b.x) && (a.y == b.y) }

Page 12: 虚数は作れる!Swift で学ぶ複素数

足し算・引き算・実数倍を定義

func + (z: Complex, w: Complex) -> Complex { return Complex(z.x + w.x, z.y + w.y) } !prefix func -(z: Complex) -> Complex { return Complex(-z.x, -z.y); } !func - (z: Complex, z: Complex) -> Complex { return Complex(z.x - w.x, z.y - w.y) } !func * (a: Double, z: Complex) -> Complex { return Complex(a * z.x, a * z.y) }

Page 13: 虚数は作れる!Swift で学ぶ複素数

次に1 = (1, 0), i = (0, 1) として、

z = x + yi の形で書けるようにする。

1 =

✓10

◆i =

✓01

z = a+ bi

Page 14: 虚数は作れる!Swift で学ぶ複素数

まず Double から生成できるようにする

struct Complex: …, FloatLiteralConvertible { … static func convertFromFloatLiteral(value: FloatLiteralType) -> Complex { ! return Complex(value, 0) } }

let z: Complex = 2.0 // Complex(2.0, 0)

Page 15: 虚数は作れる!Swift で学ぶ複素数

struct Complex: …, IntegerLiteralConvertible { … static func convertFromIntegerLiteral(value: IntegerLiteralType) -> Complex { ! return Complex(Double(value), 0) } }

let z: Complex = -1 // Complex(-1, 0)

Int についてもやっておく

Page 16: 虚数は作れる!Swift で学ぶ複素数

これで実数を複素数に「埋め込んだ」ことになる。

x

y

1 =

✓10

1 == Complex(1, 0) // true

Page 17: 虚数は作れる!Swift で学ぶ複素数

あとは 定数 i を定義すれば…

let i = Complex(0, 1)

i

x

y

i =

✓01

Page 18: 虚数は作れる!Swift で学ぶ複素数

let z = 2 + 3 * i

x

y

求めていた表現を得る!

2 =

✓20

3i =

✓03

◆z =

✓23

◆= 2 + 3i

Page 19: 虚数は作れる!Swift で学ぶ複素数

さて、いよいよ掛け算の定義。

Page 20: 虚数は作れる!Swift で学ぶ複素数

複素数の掛け算は、 実数と同じ計算規則を満たし、かつ、

となるように定義したい。

i2 = �1

Page 21: 虚数は作れる!Swift で学ぶ複素数

z = a + bi, w = c + di として、積 zw が定義できるとすれば、z = a+ bi, w = c+ di

zw = (a+ bi)(c+ di)

= a(c+ di) + bi(c+ di)分配法則

= ac+ adi+ bci+ bdi2

= ac+ adi+ bci� bd

分配法則

= ac� bd+ adi+ bci交換法則

= (ac� bd) + (ad+ bc)i分配法則

とするしかない。

zw

i2 = �1

Page 22: 虚数は作れる!Swift で学ぶ複素数

先の式で掛け算を定義してみると…

struct Complex { … } !func * (z: Complex, w: Complex) -> Complex { return Complex(z.x * w.x - z.y * w.y, z.x * w.y + z.y * w.x) }

Page 23: 虚数は作れる!Swift で学ぶ複素数

ちゃんと「掛け算の要件」を満たしている!

let α = 3 + 5 * i let β = -1 + 4 * i let γ = 4 - 7 * i !α * 1 == α // 1は単位元 α * β == β * α // 交換法則 (α * β) * γ == α * (β * γ) // 結合法則 α * (β + γ) == α * β + α * γ // 分配法則

当たり前に見えるが、テキトーに定義したのではこうならない。 これで安心して「数」として扱えるようになる。

Page 24: 虚数は作れる!Swift で学ぶ複素数

i * i == -1 // true

YES!

Page 25: 虚数は作れる!Swift で学ぶ複素数

割り算も逆数との積で定義

struct Complex { … } !func / (z: Complex, w: Complex) -> Complex { let w_inv = Complex(w.x / (w.x * w.x + w.y * w.y), -w.y / (w.x * w.x + w.y * w.y)) return z * w_inv }

Page 26: 虚数は作れる!Swift で学ぶ複素数

複素数、できました!struct Complex: Equatable, IntegerLiteralConvertible, FloatLiteralConvertible { let x: Double let y: Double init(_ x: Double, _ y: Double) { self.x = x self.y = y } static func convertFromIntegerLiteral(value: IntegerLiteralType) -> Complex { return Complex(Double(value), 0) } static func convertFromFloatLiteral(value: FloatLiteralType) -> Complex { return Complex(value, 0) } } !func == (z: Complex, w: Complex) -> Bool { return z.x == w.x && z.y == w.y } !func + (z: Complex, w: Complex) -> Complex { return Complex(z.x + w.x, z.y + w.y) } !prefix func -(z: Complex) -> Complex { return Complex(-z.x, -z.y); } !func - (z: Complex, w: Complex) -> Complex { return Complex(z.x - w.x, z.y - w.y) } !func * (z: Complex, w: Complex) -> Complex { return Complex(z.x * w.x - z.y * w.y, z.x * w.y + z.y * w.x) } !func / (z: Complex, w: Complex) -> Complex { let w_inv = Complex(w.x / (w.x * w.x + w.y * w.y), -w.y / (w.x * w.x + w.y * w.y)) return z * w_inv } !let i = Complex(0, -1)

Page 27: 虚数は作れる!Swift で学ぶ複素数

「実在しない数」 など出てきませんね?

Page 28: 虚数は作れる!Swift で学ぶ複素数

2. さわれる複素数

Page 29: 虚数は作れる!Swift で学ぶ複素数

Re

Im

複素数をおく xy 平面を「複素平面」と呼び、 x軸を実軸、y軸を虚軸と呼ぶ

z = 2 + 3i

2

3i

Page 30: 虚数は作れる!Swift で学ぶ複素数

Re

Im

複素数 z に対して、 絶対値 r = |z|, 偏角 θ= arg(z) が定義できる

r

r = |z| ✓ = arg(z)

z

z

Page 31: 虚数は作れる!Swift で学ぶ複素数

実装しときましょう

func abs(z: Complex) -> Double { return sqrt(z.x * z.x + z.y * z.y) } !func arg(z: Complex) -> Double { let r = abs(z) if(r == 0) { return 0 } let t = acos(z.x / r) return (z.y >= 0) ? t : 2 * M_PI - t }

Page 32: 虚数は作れる!Swift で学ぶ複素数

複素数は絶対値と偏角で書ける(極表示)

Re

Im

r

z = r(cos✓ + isin✓)

rcos✓

irsin✓

Page 33: 虚数は作れる!Swift で学ぶ複素数

実装しときましょう

struct Complex: … { let x: Double let y: Double init(_ x: Double, _ y: Double) { self.x = x self.y = y } init(r: Double, θ: Double) { self.x = r * cos(θ) self.y = r * sin(θ) } ! … }

Page 34: 虚数は作れる!Swift で学ぶ複素数

さて、極表示で掛け算を書き直してみると…

Page 35: 虚数は作れる!Swift で学ぶ複素数

z = r(cos✓ + isin✓), w = s(cos�+ isin�)

zw = rs{(cos✓cos�� sin✓sin�) + i(sin✓cos�+ cos✓sin�)}= cos(✓ + �) = sin(✓ + �)

= rs(cos(✓ + �) + isin(✓ + �))

に対して、

つまり…、

Page 36: 虚数は作れる!Swift で学ぶ複素数

Re

Im

r

sz

w

zw

rs

= rs(cos(✓ + �) + isin(✓ + �))zw

複素数の掛け算は、 「絶対値の積」×「偏角の和」になっていた

Page 37: 虚数は作れる!Swift で学ぶ複素数

複素平面を UIView で作ってみよう

Page 38: 虚数は作れる!Swift で学ぶ複素数

class ComplexPlane : UIView { ! var unit: CGFloat = 50.0 var scale: CGFloat = 1.0 var points: [String: Complex] = [:] var colors: [String: UIColor] = [:] subscript(name: String) -> (Complex!, UIColor!) { get { return (points[name], colors[name]) } set(value) { points[name] = value.0 colors[name] = value.1 } } override func drawRect(rect: CGRect) { … } }

Page 39: 虚数は作れる!Swift で学ぶ複素数

let cplane = ComplexPlane(frame: …) cplane.scale = 2.0 !cplane["1"] = (1, nil) cplane["i"] = (i, nil) !let z = Complex(r: 2, θ: M_PI / 3) cplane["z"] = (z, UIColor.redColor()) !let w = z * z cplane["w"] = (w, UIColor.blueColor()) !cplane.setNeedsDisplay() cplane

Page 40: 虚数は作れる!Swift で学ぶ複素数

DEMO : 動かしてみよう!

https://github.com/taketo1024/SwiftComplex

Page 41: 虚数は作れる!Swift で学ぶ複素数

3. 複素数は美しい

Page 42: 虚数は作れる!Swift で学ぶ複素数

そもそもこれはどこから出て来た?

i2 = �1

Page 43: 虚数は作れる!Swift で学ぶ複素数

(例) 方程式: x^2 + x + 1 = 0

-10 -7.5 -5 -2.5 0 2.5 5 7.5 10

-5

-2.5

2.5

5

x

2 + x+ 1 = 0

この方程式は実数の範囲では解を持たない。

y = x

2 + x+ 1

Page 44: 虚数は作れる!Swift で学ぶ複素数

形式的に2方程式の解の公式を使うと、

ここで √-3 を √3 i と置き換えて:

は、x^2 + x + 1 = 0 の解になっている。

p�3

p3i

x

2 + x+ 1 = 0

x =�1±

p12 � 4 · 1 · 12

=�1±

p�3

2

↵ =�1 +

p3i

2,� =

�1�p3i

2

Page 45: 虚数は作れる!Swift で学ぶ複素数

-10 -7.5 -5 -2.5 0 2.5 5 7.5 10

-5

-2.5

2.5

5

y = x

2 + x+ 1

y = x^2 + x + 1 は x = α, β で x 軸と交わっている…?y = x

2 + x+ 1 x = ↵,�

↵? �?

x, y を複素数と見てグラフを描くには、 残念ながら我々の世界では次元が1つ足りない。

Page 46: 虚数は作れる!Swift で学ぶ複素数

Re

Im

Re

Im

zw

w = f(z) = z^2 + z + 1 を平面から平面への写像と見て、 z の動きにあわせて w がどう動くか見てみる。z w

w = f(z) = z2 + z + 1

代わりに、

f

Page 47: 虚数は作れる!Swift で学ぶ複素数

DEMO

Page 48: 虚数は作れる!Swift で学ぶ複素数

Re

Im

Re

Imz w

z を半径を大きくしながら円上で動かす。z

Page 49: 虚数は作れる!Swift で学ぶ複素数

Re

Im

Re

Imz w

半径 1 のときに w = 0 となる点が2つある。w = 0

Page 50: 虚数は作れる!Swift で学ぶ複素数

Re

Im

Re

Im

z w

この2点が α, β で、f によって 0 に写されていた。↵,� f

↵ =�1 +

p3i

2,� =

�1�p3i

2

Page 51: 虚数は作れる!Swift で学ぶ複素数

鉛直軸は |z|sin(arg(z)) としている

zw

w = f(z) = z2 + z + 1

は平面全体をちょうど2重に覆う写像だった!

まさに「神のクレープ」

Page 52: 虚数は作れる!Swift で学ぶ複素数

y = x

2 + x+ 1

x

(放物線を y軸 に潰した形)

f

これを実数に制限したものが、 今まで y = x^2 + x + 1 だと思っていたもの。y = x

2 + x+ 1

あぁ、なんと不自由な…

Page 53: 虚数は作れる!Swift で学ぶ複素数

w = z3 + z2 � 2z + 1

f(z) = anzn + ...+ a1z + a0

は平面全体をちょうどn重に覆う写像になる。一般に

特に 0 に移る z も n 個あることになるので…

Page 54: 虚数は作れる!Swift で学ぶ複素数

代数学の基本定理

ちょうど n 個 の複素数解 を持つ!

anzn + ...+ a1z + a0 = 0n 次方程式 は、

Page 55: 虚数は作れる!Swift で学ぶ複素数

「数」は複素数まで拡張されて完成を迎える。

Page 56: 虚数は作れる!Swift で学ぶ複素数

今日伝えたかったこと

• 複素数は作れる、そして美しい。

• Swift だからこそキレイに作れた。

• 数学とプログラミングは同時に学ぶべき。

Page 57: 虚数は作れる!Swift で学ぶ複素数

次回予告(?)

• e, π, i の饗宴 ~ Swift で学ぶオイラーの公式

• 無限遠を一点に ~ SceneKit で作るリーマン球面

e,⇡, i

Page 58: 虚数は作れる!Swift で学ぶ複素数

Thanks!@taketo1024