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.9k
pythonで0を作ってみんなも神になろう
pythonで0、自然数、整数、有理数を作り、四則演算を作ります。
國友大地
September 07, 2023
Tweet
Share
Other Decks in Programming
See All in Programming
php-conference-japan-2024
tasuku43
0
380
menu基盤チームによるGoogle Cloudの活用事例~Application Integration, Cloud Tasks編~
yoshifumi_ishikura
0
120
fs2-io を試してたらバグを見つけて直した話
chencmd
0
260
生成AIでGitHubソースコード取得して仕様書を作成
shukob
0
570
Mermaid x AST x 生成AI = コードとドキュメントの完全同期への道
shibuyamizuho
1
310
nekko cloudにおけるProxmox VE利用事例
irumaru
3
490
Stackless и stackful? Корутины и асинхронность в Go
lamodatech
0
1.1k
Асинхронность неизбежна: как мы проектировали сервис уведомлений
lamodatech
0
1.1k
暇に任せてProxmoxコンソール 作ってみました
karugamo
2
760
【re:Growth 2024】 Aurora DSQL をちゃんと話します!
maroon1st
0
840
React 19でお手軽にCSS-in-JSを自作する
yukukotani
5
470
今年のアップデートで振り返るCDKセキュリティのシフトレフト/2024-cdk-security-shift-left
tomoki10
0
290
Featured
See All Featured
Optimising Largest Contentful Paint
csswizardry
33
3k
Being A Developer After 40
akosma
89
590k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.4k
Imperfection Machines: The Place of Print at Facebook
scottboms
266
13k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
7k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
YesSQL, Process and Tooling at Scale
rocio
170
14k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.3k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.9k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
Bash Introduction
62gerente
609
210k
Embracing the Ebb and Flow
colly
84
4.5k
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作った