Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
pythonで0を作ってみんなも神になろう
Search
國友大地
September 07, 2023
Programming
3
2.8k
pythonで0を作ってみんなも神になろう
pythonで0、自然数、整数、有理数を作り、四則演算を作ります。
國友大地
September 07, 2023
Tweet
Share
Other Decks in Programming
See All in Programming
Better Code Design in PHP
afilina
PRO
0
130
Jakarta EE meets AI
ivargrimstad
0
650
レガシーシステムにどう立ち向かうか 複雑さと理想と現実/vs-legacy
suzukihoge
14
2.2k
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
120
Compose 1.7のTextFieldはPOBox Plusで日本語変換できない
tomoya0x00
0
190
役立つログに取り組もう
irof
28
9.6k
CSC509 Lecture 12
javiergs
PRO
0
160
ECS Service Connectのこれまでのアップデートと今後のRoadmapを見てみる
tkikuc
2
250
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
6
2k
色々なIaCツールを実際に触って比較してみる
iriikeita
0
330
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
10
1.3k
Streams APIとTCPフロー制御 / Web Streams API and TCP flow control
tasshi
2
350
Featured
See All Featured
Building Applications with DynamoDB
mza
90
6.1k
Mobile First: as difficult as doing things right
swwweet
222
8.9k
Raft: Consensus for Rubyists
vanstee
136
6.6k
Speed Design
sergeychernyshev
25
620
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
BBQ
matthewcrist
85
9.3k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
Side Projects
sachag
452
42k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
Optimising Largest Contentful Paint
csswizardry
33
2.9k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Agile that works and the tools we love
rasmusluckow
327
21k
Transcript
Pythonで0を作ろう
はじめまして! 神です。
はじめまして! 今日は数を作っていきます。 理由は、数を作りたいからです。
ルール • Pythonを使う • int, float型とfor文禁止(ただし、一部省略記法としてintを使います) • 有理数の四則演算まで作る
0を作りたい 材料がない!
0を作ろう 世界にまだ何も存在していないので、0を作る材料がありません。 しかしこの世界には「材料がない」という唯一の材料があるのでこれを使います zero = []
1を作ろう この世界には「材料がない」という唯一の材料がありますが使ってしまいました しかしご安心を。この世界には今、材料が生まれました! それを使いましょう! zero = [] one = [zero]
# = [[]]
2を作ろう 2はどうしましょうか。 two = [one]としてもいいし、two = [zero, zero]としてもいいです。 ただ、今回はこうします。 zero
= [] one = [zero] # = [[]] two = [zero, one] # = [[], [[]]]
自然数を作ろう 実は two + [two] = [zero, one] + [two]
= [zero, one, two] = threeとなります。 以降はそうやって自然数を作りましょう。 zero = [] one = [zero] # = [[]] two = [zero, one] # = [[], [[]]] three = two + [two] # = [zero, one, two] ※0は大学数学においては自然数に含む
1を足す関数を作ろう さっき言ったようにこうやって x + 1を計算できます。 # 1を足す関数 後者関数 successor function
def suc(x: Natural) -> Natural: """ x + 1 を計算する""" return x + [x] ※Natural型 = list型
1を引く関数を作ろう 1を引く関数はリストの一番最後を消せばいいのでこうすればいいです。 int型の「-1」を使ってますが、pop()を使えばいいので省略記法として使います。 def pre(x: Natural) -> Natural: """ x
- 1 を計算する x=0ならエラー""" return x[:-1] 今できること • 1を足す
大小関係を作ろう なんと大小関係が1行で判定できる。最高! def is_bigger(x: Natural, y: Natural) -> bool: """
x < y かを判定する""" return x in y 今できること • 1を足す • 1を引く
足し算を作ろう 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を引く • 大小関係
掛け算を作ろう 足し算を繰り返して再帰で書きます。 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を引く • 大小関係 • 足し算
掛け算まで作れた やったー!! 今できること • 1を足す • 1を引く • 大小関係 •
足し算 • 掛け算
引き算を作りたい 引き算を「1を引く」の再帰で作ると答えが負のときに困るので、 やりたくないです。 どうにかして x - y = z を今できることで表現できないでしょうか…?
今できること • 1を足す • 1を引く • 大小関係 • 足し算 • 掛け算 x - y = z
引き算を作りたい 引き算を「1を引く」の再帰で作ると答えが負のときに困るので、 やりたくないです。 どうにかして x - y = z を今できることで表現できないでしょうか…?
今できること • 1を足す • 1を引く • 大小関係 • 足し算 • 掛け算 x - y = z x = z + y ←!!!!!!
整数を作ろう 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型は異なる
整数を作ろう 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型は異なる
整数の「=」を作ろう 整数が等しいかを判定するために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は許容
整数の足し算を作ろう (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を引く ◦ 大小関係 ◦ 足し算 ◦ 掛け算 • 整数 ◦ 「=」
整数の単項マイナスを作ろう a-b = b-aなのでそのまま def neg_i(x: Integer) -> Integer: """
-x を計算する""" return (x[1], x[0]) 今できること • 自然数 ◦ 1を足す ◦ 1を引く ◦ 大小関係 ◦ 足し算 ◦ 掛け算 • 整数 ◦ 「=」 ◦ 足し算
整数の引き算を作ろう 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を引く ◦ 大小関係 ◦ 足し算 ◦ 掛け算 • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転
整数の掛け算を作ろう テキトーにやれば面倒だが出来る。 (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を引く ◦ 大小関係 ◦ 足し算 ◦ 掛け算 • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算
整数と引き算が作れた 今できること • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転
◦ 引き算 ◦ 掛け算 もう自然数は整数の下位互換なので要りません やったー!!
割り算を作りたい x / y = z ↑ これを足し算引き算掛け算だけで表現できないか 今できること •
整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算
割り算を作りたい x / y = z x = z *
y 今できること • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算 ←!!!!!!
有理数を作ろう なんと!有理数は2つの整数から作ることが出来ます!知ってた。 有理数 x / y を(x, y) と表します! Rational
= tuple[Integer, Integer] 今できること • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算
有理数の「=」を作ろう 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]) ) 今できること • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算
有理数の掛け算を作ろう 有理数はみなさん御存知の通り掛け算が一番楽なので作ります。 (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])) 今できること • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算 • 有理数 ◦ 「=」
有理数の割り算を作ろう 有理数はみなさん御存知の通り割り算が二番楽(?)なので作ります。 (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])) 今できること • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算 • 有理数 ◦ 「=」 ◦ 掛け算
有理数の単項マイナスを作ろう 分数をマイナスにするのは分子にマイナスつけるだけです。 def neg_r(x: Rational) -> Rational: """ -x を計算する"""
return (neg_i(x[0]), x[1]) 今できること • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算 • 有理数 ◦ 「=」 ◦ 掛け算 ◦ 割り算
有理数の足し算を作ろう なんかごちゃごちゃ計算したらできます。 読まなくていいです。 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) 今できること • 整数 ◦ 「=」 ◦ 足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算 • 有理数 ◦ 「=」 ◦ 掛け算 ◦ 割り算 ◦ 正負逆転
有理数の引き算を作ろう なんかごちゃごちゃ計算したらできます2。 読まなくていいです2。 …と思いきや足し算と単項マイナスがあるので楽です。 今できること • 整数 ◦ 「=」 ◦
足し算 ◦ 正負逆転 ◦ 引き算 ◦ 掛け算 • 有理数 ◦ 「=」 ◦ 掛け算 ◦ 割り算 ◦ 正負逆転 ◦ 足し算 def minus_r(x: Rational, y: Rational) -> Rational: """ x-y を計算する""" return plus_r(x, neg_r(y))
有理数と割り算が作れた もう整数は有理数の下位互換なので要りません やったー!! 今できること • 有理数 ◦ 「=」 ◦ 掛け算
◦ 割り算 ◦ 正負逆転 ◦ 足し算 ◦ 引き算
結論:四則演算がリストから作れた! 今回の数や演算の作り方は、数学における数の作り方の内、 もっともメジャーなもの(ZFC)とほぼ同じです。 数学に「リスト」という構造は、0や1がないと作れない(はず…) ので、 本来は集合をつかって定義されます! なお有理数をさらに進めた実数については、 デデキントカットか無限数列の極限で定義されますが、 どちらも有理数を無限個使うのでコンピュータじゃ無理です。 というか現実では不可能。
うれしい! 満足したので帰ります。
参考資料 元ネタ https://www.nicovideo.jp/watch/sm32548726 琴葉姉妹の数学キソ論:第1回「1+1=2を証明して?」 ↑全人類見ろ https://qiita.com/taketo1024/items/2ab856d21bf9b9f30357 「Swiftで自然数を作ってみた(ペアノの公理)」 他、https://qiita.com/search?q=自然数を作る 内の記事
Qiitaの「数字を作る」系の記事、 だいたい足し算・掛け算までしかやらないがちなのでこのLT作った