没有机器基元的数字表示

时间:2010-07-08 14:59:11

标签: types numbers

概要

在任何表示整数的语言中发布示例,而不直接使用机器整数。包括的映射和用户定义类型的。空间和/或时间效率的要点。

原始问题

a certain rather bold answer关于面向对象编程问题的评论中,我表示我相信机器原语不是对象,但无法真正证实这种说法,就像那张海报一样。答案无法证实他关于面向对象哲学的普遍性和基本性的主张。

这让我思考。在C ++中,机器基元不参与类层次结构的语言是否可以定义一个对象类型 - 比如Integer - 使用机器基元存储它的价值?

this beautiful bit of template hackery实现教会数字。不幸的是,由于整数和教堂数字之间的转换严格地发生在编译时,因此没有办法绕过用户输入使用机器整数。

所以我正在寻找的是与上述相同的运行时,但不一定使用具有合理空间要求的教会数字,可以用C ++等语言实现,而不是更高 - 订单功能。我希望看到其他语言的例子,特别是那些利用有趣的动态打字技巧的例子。只要存储的地址严格地使用而不是其整数值,指针和函数指针就不应算作基元。

用于容纳所有整数(即不仅仅是整数)的奖励积分,以及用于设计也可以实现浮点数的系统的超级奖励积分。

为了避免任何不愉快,并鼓励礼貌的讨论,我从一开始就把它作为一个社区维基问题。

2 个答案:

答案 0 :(得分:2)

这里有一个可用于正整数的类。并且可以很容易地扩展到负面因素。 它支持加法,减法,相等,不等式和乘法。可以基于现有运营商来划分分部。总而言之,我会说它几乎代表整数,并且没有任何简单类型的使用。实际上,班级使用的唯一类型就是自我。

实现基本上是一个带有一些优化的链接列表,因此每次操作都不需要遍历列表。

public class MyInt
    {
        private MyInt _previous;
        private MyInt _first;
        private bool isEven;

        private MyInt(MyInt previous)
        {
            next++;
            _previous = previous;
            isEven = previous == null ? true : !previous.isEven;
            getFirst();
            x = next;
        }

        private void getFirst()
        {
            if (_previous == null)
                _first = null;
            else if (_previous._first == null)
                _first = this;
            else
                _first = _previous._first;
        }

        private MyInt(MyInt copy, bool dontuse)
        {
            _previous = copy._previous == null ? null : new MyInt(copy._previous,true);
            getFirst();
            x = copy.x;
        }

        public static MyInt operator +(MyInt lhs, MyInt rhs)
        {
            if (object.ReferenceEquals(lhs, rhs))
                rhs = new MyInt(rhs, true);
            if (lhs == MyInt.Zero)
                return rhs;
            if (rhs == MyInt.Zero)
                return lhs;
            else
            {
                var isEven = rhs.isEven == lhs.isEven;
                var result = new MyInt(rhs, true);
                result._first._previous = lhs;
                result._first = lhs._first;
                result.isEven = isEven;
                return result;
            }
        }

        public static MyInt operator -(MyInt lhs, MyInt rhs)
        {
            if (lhs == rhs)
                return MyInt.Zero;
            if (rhs == MyInt.Zero)
                return lhs;
            if (lhs == MyInt.Zero)
                throw new InvalidOperationException("Negatives not supported");
            else
            {
                return lhs._previous - rhs._previous;
            }
        }

        public static MyInt operator --(MyInt un)
        {
            if (un == MyInt.Zero)
                throw new InvalidOperationException("Negatives not supported");
            return un._previous;
        }

        public static MyInt operator *(MyInt lhs, MyInt rhs)
        {
            if (lhs == MyInt.Zero || rhs == MyInt.Zero)
                return MyInt.Zero;

            var temp = lhs;
            var one = One;
            var two = one + one;
            var zero = MyInt.Zero;
            var dbl = lhs + lhs;
            if (rhs == MyInt.One)
                return lhs;
            if (rhs == two)
                return dbl;
            for (MyInt times = rhs + one; times._previous._previous != zero && times._previous != zero; times = times-two)
            {
                temp = temp + dbl;
            }
            if (rhs.isEven)
                temp = temp - lhs;
            return temp;
        }

        public static bool operator ==(MyInt lhs, MyInt rhs)
        {
            if (object.ReferenceEquals(lhs, null) && object.ReferenceEquals(rhs, null))
                return true;
            if ((object.ReferenceEquals(lhs, null) || object.ReferenceEquals(rhs, null)))
                return false;
            if (object.ReferenceEquals(lhs._previous, null) && object.ReferenceEquals(rhs._previous, null))
                return true;
            if ((object.ReferenceEquals(lhs._previous, null) || object.ReferenceEquals(rhs._previous, null)))
                return false;

            return (lhs._previous == rhs._previous);
        }

        public static bool operator !=(MyInt lhs, MyInt rhs)
        {
            return !(lhs == rhs);
        }

        public override bool Equals(object obj)
        {
            return obj is MyInt && ((MyInt)obj) == this;
        }

        public static MyInt Zero
        {
            get
            {
                return new MyInt(null);
            }
        }

        public static MyInt One
        {
            get
            {
                return new MyInt(new MyInt(null));
            }
        }
    }

答案 1 :(得分:1)

总有Lisp,其中0可以表示为()(空列表),1表示(()),2表示(() ()),等等。一天,但当然没有任何Lisp实现使用它,因为它太慢而不能相信。