Slide 1

Slide 1 text

Pythonで0を作ろう

Slide 2

Slide 2 text

はじめまして! 神です。

Slide 3

Slide 3 text

はじめまして! 今日は数を作っていきます。 理由は、数を作りたいからです。

Slide 4

Slide 4 text

ルール ● Pythonを使う ● int, float型とfor文禁止(ただし、一部省略記法としてintを使います) ● 有理数の四則演算まで作る

Slide 5

Slide 5 text

0を作りたい 材料がない!

Slide 6

Slide 6 text

0を作ろう 世界にまだ何も存在していないので、0を作る材料がありません。 しかしこの世界には「材料がない」という唯一の材料があるのでこれを使います zero = []

Slide 7

Slide 7 text

1を作ろう この世界には「材料がない」という唯一の材料がありますが使ってしまいました しかしご安心を。この世界には今、材料が生まれました! それを使いましょう! zero = [] one = [zero] # = [[]]

Slide 8

Slide 8 text

2を作ろう 2はどうしましょうか。 two = [one]としてもいいし、two = [zero, zero]としてもいいです。 ただ、今回はこうします。 zero = [] one = [zero] # = [[]] two = [zero, one] # = [[], [[]]]

Slide 9

Slide 9 text

自然数を作ろう 実は two + [two] = [zero, one] + [two] = [zero, one, two] = threeとなります。 以降はそうやって自然数を作りましょう。 zero = [] one = [zero] # = [[]] two = [zero, one] # = [[], [[]]] three = two + [two] # = [zero, one, two] ※0は大学数学においては自然数に含む

Slide 10

Slide 10 text

1を足す関数を作ろう さっき言ったようにこうやって x + 1を計算できます。 # 1を足す関数 後者関数 successor function def suc(x: Natural) -> Natural: """ x + 1 を計算する""" return x + [x] ※Natural型 = list型

Slide 11

Slide 11 text

1を引く関数を作ろう 1を引く関数はリストの一番最後を消せばいいのでこうすればいいです。 int型の「-1」を使ってますが、pop()を使えばいいので省略記法として使います。 def pre(x: Natural) -> Natural: """ x - 1 を計算する x=0ならエラー""" return x[:-1] 今できること ● 1を足す

Slide 12

Slide 12 text

大小関係を作ろう なんと大小関係が1行で判定できる。最高! def is_bigger(x: Natural, y: Natural) -> bool: """ x < y かを判定する""" return x in y 今できること ● 1を足す ● 1を引く

Slide 13

Slide 13 text

足し算を作ろう 1を足すことと1を引くことしかできず、for文も禁止なので再帰で書きます。 x + 0 = x、x+y = (x+1)+(y-1)。それはそう。 def plus(x: Natural, y: Natural) -> Natural: if y == zero: return x # x + 0 = x else: return plus(suc(x), pre(y)) # x+y = (x+1)+(y-1) 今できること ● 1を足す ● 1を引く ● 大小関係

Slide 14

Slide 14 text

掛け算を作ろう 足し算を繰り返して再帰で書きます。 x * 0 = 0、x * y = x * (y-1) + x。それはそう。 def mul(x: Natural, y: Natural) -> Natural: if y == zero: return zero # x * 0 = 0 else: # x * y = x * (y-1) + x return plus(mul(x, pre(y)), x) 今できること ● 1を足す ● 1を引く ● 大小関係 ● 足し算

Slide 15

Slide 15 text

掛け算まで作れた やったー!! 今できること ● 1を足す ● 1を引く ● 大小関係 ● 足し算 ● 掛け算

Slide 16

Slide 16 text

引き算を作りたい 引き算を「1を引く」の再帰で作ると答えが負のときに困るので、 やりたくないです。 どうにかして x - y = z を今できることで表現できないでしょうか…? 今できること ● 1を足す ● 1を引く ● 大小関係 ● 足し算 ● 掛け算 x - y = z

Slide 17

Slide 17 text

引き算を作りたい 引き算を「1を引く」の再帰で作ると答えが負のときに困るので、 やりたくないです。 どうにかして x - y = z を今できることで表現できないでしょうか…? 今できること ● 1を足す ● 1を引く ● 大小関係 ● 足し算 ● 掛け算 x - y = z x = z + y ←!!!!!!

Slide 18

Slide 18 text

整数を作ろう a - b = c - d の時、 a + d = c + b です。 整数を自然数の2つ組で表現しましょう! 自然数a,bを使って整数 a-bを(a, b)と表現します! (1,4) = -3 , (0,0) = 0, (20, 21) = -1, (0,3) = -3 です! Integer = tuple[Natural, Natural] 今できること ● 1を足す ● 1を引く ● 大小関係 ● 足し算 ● 掛け算 ※int型とInteger型は異なる

Slide 19

Slide 19 text

整数を作ろう a - b = c - d の時、 a + d = c + b です。 整数を自然数の2つ組で表現しましょう! 自然数a,bを使って整数 a-bを(a, b)と表現します! (1,4) = -3 , (0,0) = 0, (20, 21) = -1, (0,3) = -3 です! (1,4) = (0,3) になってるけど大丈夫? Integer = tuple[Natural, Natural] 今できること ● 1を足す ● 1を引く ● 大小関係 ● 足し算 ● 掛け算 ※int型とInteger型は異なる

Slide 20

Slide 20 text

整数の「=」を作ろう 整数が等しいかを判定するためにInteger型の「=」を作る。 a-b = c-d なら a+d = b+c なので簡単 x[0]やx[1]はNatural型なので足し算できる! def eq_i(x: Integer, y: Integer) -> bool: """x[0] - x[1] == y[0] - y[1] かを判定する""" return plus(x[0], y[1]) == plus(y[0], x[1]) 今できること ● 自然数 ○ 1を足す ○ 1を引く ○ 大小関係 ○ 足し算 ○ 掛け算 ※Integerを型ではなくクラスで表現すれば添字 [0][1]は使わずに済むので、ここでの int型0,1は許容

Slide 21

Slide 21 text

整数の足し算を作ろう (a-b) + (c-d) = (a+c) - (b+d)なので自然数の足し算だけで作れる! def plus_i(x: Integer, y: Integer) -> Integer: """ x+y を計算する""" # a-b + c-d = (a+c) - (b+d) return (plus(x[0], y[0]), plus(x[1], y[1])) 今できること ● 自然数 ○ 1を足す ○ 1を引く ○ 大小関係 ○ 足し算 ○ 掛け算 ● 整数 ○ 「=」

Slide 22

Slide 22 text

整数の単項マイナスを作ろう a-b = b-aなのでそのまま def neg_i(x: Integer) -> Integer: """ -x を計算する""" return (x[1], x[0]) 今できること ● 自然数 ○ 1を足す ○ 1を引く ○ 大小関係 ○ 足し算 ○ 掛け算 ● 整数 ○ 「=」 ○ 足し算

Slide 23

Slide 23 text

整数の引き算を作ろう x - y = x + (-y)より作れる。 def minus_i(x: Integer, y: Integer) -> Integer: """ x-y を計算する""" return plus_i(x, neg_i(y)) # x-y = x + (-y) 今できること ● 自然数 ○ 1を足す ○ 1を引く ○ 大小関係 ○ 足し算 ○ 掛け算 ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転

Slide 24

Slide 24 text

整数の掛け算を作ろう テキトーにやれば面倒だが出来る。 (a-b)*(c-d)=(a*c-b*c) - (a*c - b*d) def mul_i(x: Integer, y: Integer) -> Integer: x_mul_y0: Integer = (mul(x[0],y[0]), mul(x[1],y[0])) x_mul_y1: Integer = (mul(x[0],y[1]), mul(x[1],y[1])) return minus_i(x_mul_y0, x_mul_y1) 今できること ● 自然数 ○ 1を足す ○ 1を引く ○ 大小関係 ○ 足し算 ○ 掛け算 ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算

Slide 25

Slide 25 text

整数と引き算が作れた 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算 もう自然数は整数の下位互換なので要りません やったー!!

Slide 26

Slide 26 text

割り算を作りたい x / y = z ↑ これを足し算引き算掛け算だけで表現できないか 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算

Slide 27

Slide 27 text

割り算を作りたい x / y = z x = z * y 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算 ←!!!!!!

Slide 28

Slide 28 text

有理数を作ろう なんと!有理数は2つの整数から作ることが出来ます!知ってた。 有理数 x / y を(x, y) と表します! Rational = tuple[Integer, Integer] 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算

Slide 29

Slide 29 text

有理数の「=」を作ろう a / b = c / d ならば a * d = c * bなのでこうなります。 def eq_r(x: Rational, y: Rational) -> bool: return eq_i( mul_i(x[0], y[1]), mul_i(x[1], x[0]) ) 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算

Slide 30

Slide 30 text

有理数の掛け算を作ろう 有理数はみなさん御存知の通り掛け算が一番楽なので作ります。 (a / b) * (c / d) = (a*c) / (b*d) def mul_r(x: Rational, y: Rational) -> Rational: """ x*y を計算する""" return (mul_i(x[0], y[0]), mul_i(x[1], y[1])) 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算 ● 有理数 ○ 「=」

Slide 31

Slide 31 text

有理数の割り算を作ろう 有理数はみなさん御存知の通り割り算が二番楽(?)なので作ります。 (a / b) / (c / d) = (a*d) / (b*c) def div_r(x: Rational, y: Rational) -> Rational: """ x/y を計算する""" return (mul_i(x[0], y[1]), mul_i(x[1], y[0])) 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算 ● 有理数 ○ 「=」 ○ 掛け算

Slide 32

Slide 32 text

有理数の単項マイナスを作ろう 分数をマイナスにするのは分子にマイナスつけるだけです。 def neg_r(x: Rational) -> Rational: """ -x を計算する""" return (neg_i(x[0]), x[1]) 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算 ● 有理数 ○ 「=」 ○ 掛け算 ○ 割り算

Slide 33

Slide 33 text

有理数の足し算を作ろう なんかごちゃごちゃ計算したらできます。 読まなくていいです。 def plus_r(x: Rational, y: Rational) -> Rational: numerator = plus_i(mul_i(x[0], y[1]), mul_i(x[1], y[0])) denominator = mul_i(x[1], y[1]) return (numerator, denominator) 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算 ● 有理数 ○ 「=」 ○ 掛け算 ○ 割り算 ○ 正負逆転

Slide 34

Slide 34 text

有理数の引き算を作ろう なんかごちゃごちゃ計算したらできます2。 読まなくていいです2。 …と思いきや足し算と単項マイナスがあるので楽です。 今できること ● 整数 ○ 「=」 ○ 足し算 ○ 正負逆転 ○ 引き算 ○ 掛け算 ● 有理数 ○ 「=」 ○ 掛け算 ○ 割り算 ○ 正負逆転 ○ 足し算 def minus_r(x: Rational, y: Rational) -> Rational: """ x-y を計算する""" return plus_r(x, neg_r(y))

Slide 35

Slide 35 text

有理数と割り算が作れた もう整数は有理数の下位互換なので要りません やったー!! 今できること ● 有理数 ○ 「=」 ○ 掛け算 ○ 割り算 ○ 正負逆転 ○ 足し算 ○ 引き算

Slide 36

Slide 36 text

結論:四則演算がリストから作れた! 今回の数や演算の作り方は、数学における数の作り方の内、 もっともメジャーなもの(ZFC)とほぼ同じです。 数学に「リスト」という構造は、0や1がないと作れない(はず…) ので、 本来は集合をつかって定義されます! なお有理数をさらに進めた実数については、 デデキントカットか無限数列の極限で定義されますが、 どちらも有理数を無限個使うのでコンピュータじゃ無理です。 というか現実では不可能。

Slide 37

Slide 37 text

うれしい! 満足したので帰ります。

Slide 38

Slide 38 text

参考資料 元ネタ https://www.nicovideo.jp/watch/sm32548726 琴葉姉妹の数学キソ論:第1回「1+1=2を証明して?」
 ↑全人類見ろ
 https://qiita.com/taketo1024/items/2ab856d21bf9b9f30357 「Swiftで自然数を作ってみた(ペアノの公理)」
 
 他、https://qiita.com/search?q=自然数を作る 内の記事
 Qiitaの「数字を作る」系の記事、
 だいたい足し算・掛け算までしかやらないがちなのでこのLT作った