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
3.2k
pythonで0を作ってみんなも神になろう
pythonで0、自然数、整数、有理数を作り、四則演算を作ります。
國友大地
September 07, 2023
Tweet
Share
Other Decks in Programming
See All in Programming
「App Intent」よくわからんけどすごい!
rinngo0302
1
120
テスト環境にCDを導入してみた
yasaigaoisi
0
100
Porting a visionOS App to Android XR
akkeylab
0
900
20250704_教育事業におけるアジャイルなデータ基盤構築
hanon52_
5
1.2k
新メンバーも今日から大活躍!SREが支えるスケールし続ける組織のオンボーディング
honmarkhunt
5
9.2k
PHPUnitの限界をPlaywrightで補完するテストアプローチ
yuzneri
0
260
[SRE NEXT] 複雑なシステムにおけるUser Journey SLOの導入
yakenji
0
690
AI Ramen Fight
yusukebe
0
100
MySQL9でベクトルカラム登場!PHP×AWSでのAI/類似検索はこう変わる
suguruooki
1
210
Workers を定期実行する方法は一つじゃない
rokuosan
0
120
状態遷移図を書こう / Sequence Chart vs State Diagram
orgachem
PRO
2
250
コーディングエージェント概観(2025/07)
itsuki_t88
0
120
Featured
See All Featured
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
18
1k
The Cult of Friendly URLs
andyhume
79
6.5k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
126
53k
Done Done
chrislema
184
16k
Gamification - CAS2011
davidbonilla
81
5.4k
Practical Orchestrator
shlominoach
189
11k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.5k
Why You Should Never Use an ORM
jnunemaker
PRO
58
9.5k
The Pragmatic Product Professional
lauravandoore
35
6.8k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
840
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
760
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作った