Types 没有机器原语的数字表示法
简介 在不直接使用机器整数的情况下,使用任何表示整数类型的语言发布示例。包括与用户定义类型之间的映射。空间和/或时间效率方面的得分 原始问题 在对一个关于面向对象编程的问题的评论中,我陈述了我的信念,即机器原语不是对象,但无法真正证实这一主张,正如该答案的海报无法证实他关于面向对象哲学的普遍性和基本性质的主张一样 这让我开始思考。在C++中,机器原语不参与类层次结构的语言,是否可以定义一个对象类型,例如“代码>整数< /代码>——不使用机器原语来存储它的值?< /p> 有一种实现教堂数字的方法。不幸的是,由于整数和教会数字之间的转换严格在编译时进行,因此无法避免使用机器整数进行用户输入Types 没有机器原语的数字表示法,types,numbers,Types,Numbers,简介 在不直接使用机器整数的情况下,使用任何表示整数类型的语言发布示例。包括与用户定义类型之间的映射。空间和/或时间效率方面的得分 原始问题 在对一个关于面向对象编程的问题的评论中,我陈述了我的信念,即机器原语不是对象,但无法真正证实这一主张,正如该答案的海报无法证实他关于面向对象哲学的普遍性和基本性质的主张一样 这让我开始思考。在C++中,机器原语不参与类层次结构的语言,是否可以定义一个对象类型,例如“代码>整数< /代码>——不使用机器原语来存储它的值?< /p> 有一种实现教堂数字的方法。
所以我所寻找的是运行时等价于上述的,虽然不一定要使用教堂数字,并且具有合理的空间需求,可以用C++语言实现,而不需要高阶函数。我也希望看到其他语言中的示例,尤其是那些使用有趣的动态键入技巧的示例。只要存储的地址严格按原语使用,而不是按其整数值使用,指针和函数指针就不能算作原语
用于容纳所有整数(即,不仅仅是整数)的奖励积分,以及用于设计还可以实现浮点数的系统的超级奖励积分为了避免任何不愉快,并鼓励礼貌的讨论,我从一开始就把这个问题作为一个社区维基问题。总是有Lisp,其中0可以表示为
()
(空列表),1是(())
,2是(())
,等等。这在当时就已经被证明了,当然,没有任何Lisp实现真正使用它,因为它太慢了,令人难以置信。这里有一个类可以用于正整数。也可以很容易地扩展到解释消极因素。
它支持加法、减法、等式、不等式和乘法。可根据现有运营商进行划分。总之,我想说它几乎代表整数,没有任何简单类型的用处。实际上,类使用的唯一类型是它自己
该实现基本上是一个带有一些优化的链接列表,因此不需要对每个操作都遍历该列表
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));
}
}
}
你到底想干什么?最终,所有这些都归结为机器整数。您可以将自然值编码为任何元素类型的列表(或向量等)。空列表为零,加法为串联。你在寻找比这更复杂的东西吗?“容纳所有整数(即,不只是整数)的额外积分”--嗯?@Alexandre,我很确定这个想法只是为了好玩。@Alexandre:或者我引发了一场关于替代数字表示法的非常有趣的讨论,或者我向大家展示了,不管你从哪个角度看,它都可以归结为机器整数,面向对象编程是一种与计算机相对应的哲学,与函数式编程没有什么区别。听起来有点像自然数的集合论定义。这是一个非常有趣的基于列表的实现!我还认为
bool
在这里很好,因为它可以用引用类型(null表示false,non-null表示true)来实现。基本上bool只是我的懒惰。我需要一个复制构造函数,但因为我已经有了一个使用MyInt的构造函数,所以我需要一个不同的签名(是的,我知道它不漂亮:)。当然,是的,它可以实现为null/notnull或只是ommitted。这是对乘法运算符的优化