EeBlog(テクニカルブログ)

ペアノの公理

論理だけで自然数という概念を定義したペアノの公理というものがあります。ペアノの公理によると自然数はある5つの条件を満たす、と定義されるそうです。ペアノの公理がどのようなものかは下記リンク先のWikipediaのページを見てください。
ペアノの公理 – Wikipedia http://ja.wikipedia.org/wiki/%E3%83%9A%E3%82%A2%E3%83%8E%E3%81%AE%E5%85%AC%E7%90%86
自然数が満たすべき条件が決められるということは、この条件を満たすようにオブジェクトを定義すれば、それは自然数と同等のオブジェクトになるということです。

ということでプリミティブ型やライブラリの数値型を利用しないで自然数を実装してみました。

number/natural/PeanoSystem.java

package number.natural;

public abstract class PeanoSystem<E> {

    public abstract E zero();
    public abstract E succ(E n);

    public E add(E a, E b) {
 return f(a, b, zero());
    }

    public E sub(E a, E b) {
 return f(zero(), a, b);
    }

    private E f(E a, E b, E c) {
 return b.equals(c) ? a : f(succ(a), b, succ(c));
    }
}

number/natural/Natural.java

package number.natural;

public class Natural extends PeanoSystem<Object> {

    @Override
    public Object succ(Object n) {
 return new Succ(n);
    }

    @Override
    public Object zero() {
 return new Zero();
    }

    private static class Zero {

 @Override
 public boolean equals(Object obj) {
     return getClass().isInstance(obj);
 }
    }

    private static class Succ {

 private Object n;

 public Succ(Object n) {
     this.n = n;
 }

 @Override
 public boolean equals(Object obj) {
     return getClass().isInstance(obj)
     && n.equals(getClass().cast(obj).n);
 }
    }

    public static void main(String[] args) {
 Natural sys = new Natural();
 Object one = sys.succ(sys.zero());
 Object two = sys.add(one, one);
 Object four = sys.add(two, two);
 Object eight = sys.add(four, four);
 for (Object i = sys.zero(); !i.equals(eight); i = sys.add(i, one)) {
     System.out.print(".");
 } 
    }
}

演算は足し算と引き算しかできない(しかも引く数が引かれる数より多いと無限ループに陥るという欠陥がある)、十進数表示もできない、メモリ効率は相当に悪いと欠点だらけなのでまったく実用性がありませんが、唯一の長所は int などの数値型と異なり理論的には最大値に限界がありませんので、メモリの許す限り大きな値を表すことができるということでしょうか。まあそれは BigInteger を使えばよいという話ですが。

とはいえ自然数、もっというと数という根源的な概念をさらに分解して考えるというのはなかなかおもしろいものです。