Upgrade to Pro — share decks privately, control downloads, hide ads and more …

pythonで0を作ってみんなも神になろう

國友大地
September 07, 2023

 pythonで0を作ってみんなも神になろう

pythonで0、自然数、整数、有理数を作り、四則演算を作ります。

國友大地

September 07, 2023
Tweet

Other Decks in Programming

Transcript

  1. Pythonで0を作ろう

    View Slide

  2. はじめまして!
    神です。

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  13. 足し算を作ろう
    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を引く
    ● 大小関係

    View Slide

  14. 掛け算を作ろう
    足し算を繰り返して再帰で書きます。
    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を引く
    ● 大小関係
    ● 足し算

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. 整数を作ろう
    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型は異なる

    View Slide

  19. 整数を作ろう
    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型は異なる

    View Slide

  20. 整数の「=」を作ろう
    整数が等しいかを判定するために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は許容

    View Slide

  21. 整数の足し算を作ろう
    (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を引く
    ○ 大小関係
    ○ 足し算
    ○ 掛け算
    ● 整数
    ○ 「=」

    View Slide

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

    View Slide

  23. 整数の引き算を作ろう
    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を引く
    ○ 大小関係
    ○ 足し算
    ○ 掛け算
    ● 整数
    ○ 「=」
    ○ 足し算
    ○ 正負逆転

    View Slide

  24. 整数の掛け算を作ろう
    テキトーにやれば面倒だが出来る。
    (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を引く
    ○ 大小関係
    ○ 足し算
    ○ 掛け算
    ● 整数
    ○ 「=」
    ○ 足し算
    ○ 正負逆転
    ○ 引き算

    View Slide

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

    View Slide

  26. 割り算を作りたい
    x / y = z

    これを足し算引き算掛け算だけで表現できないか
    今できること
    ● 整数
    ○ 「=」
    ○ 足し算
    ○ 正負逆転
    ○ 引き算
    ○ 掛け算

    View Slide

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

    View Slide

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

    View Slide

  29. 有理数の「=」を作ろう
    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])
    )
    今できること
    ● 整数
    ○ 「=」
    ○ 足し算
    ○ 正負逆転
    ○ 引き算
    ○ 掛け算

    View Slide

  30. 有理数の掛け算を作ろう
    有理数はみなさん御存知の通り掛け算が一番楽なので作ります。
    (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]))
    今できること
    ● 整数
    ○ 「=」
    ○ 足し算
    ○ 正負逆転
    ○ 引き算
    ○ 掛け算
    ● 有理数
    ○ 「=」

    View Slide

  31. 有理数の割り算を作ろう
    有理数はみなさん御存知の通り割り算が二番楽(?)なので作ります。
    (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]))
    今できること
    ● 整数
    ○ 「=」
    ○ 足し算
    ○ 正負逆転
    ○ 引き算
    ○ 掛け算
    ● 有理数
    ○ 「=」
    ○ 掛け算

    View Slide

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

    View Slide

  33. 有理数の足し算を作ろう
    なんかごちゃごちゃ計算したらできます。
    読まなくていいです。
    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)
    今できること
    ● 整数
    ○ 「=」
    ○ 足し算
    ○ 正負逆転
    ○ 引き算
    ○ 掛け算
    ● 有理数
    ○ 「=」
    ○ 掛け算
    ○ 割り算
    ○ 正負逆転

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  38. 参考資料
    元ネタ
    https://www.nicovideo.jp/watch/sm32548726
    琴葉姉妹の数学キソ論:第1回「1+1=2を証明して?」

    ↑全人類見ろ

    https://qiita.com/taketo1024/items/2ab856d21bf9b9f30357
    「Swiftで自然数を作ってみた(ペアノの公理)」


    他、https://qiita.com/search?q=自然数を作る 内の記事

    Qiitaの「数字を作る」系の記事、

    だいたい足し算・掛け算までしかやらないがちなのでこのLT作った


    View Slide