我正在编写一种编程语言,今天我得到了可以编译阶乘函数(递归)的点,但是由于整数的最大值,我可以获得的最大值是阶乘(12)。什么是处理任意最大大小的整数的技术。目前,该语言通过将代码转换为C ++来实现。
答案 0 :(得分:18)
如果需要大于32位,可以考虑使用64位整数(long long),或使用或编写任意精度数学库,例如: GNU MP
答案 1 :(得分:5)
如果你想要推出自己的任意精度库,请参阅Knuth的精神数学算法,他的巨着的第2卷。
答案 2 :(得分:3)
如果您将其构建为一种语言(出于学习目的,我猜),我想我可能会写一个小BCD库。只需将BCD编号存储在字节数组中即可。
事实上,使用当今巨大的存储能力,您可能只使用一个字节数组,其中每个字节只保存一个数字(0-9)。然后编写自己的例程来添加,减去乘法并除以字节数组。
(Divide很难,但我打赌你可以在某处找到一些代码。)
我可以给你一些类似Java的伪代码但是现在不能从头开始做C ++:
class BigAssNumber {
private byte[] value;
// This constructor can handle numbers where overflows have occurred.
public BigAssNumber(byte[] value) {
this.value=normalize(value);
}
// Adds two numbers and returns the sum. Originals not changed.
public BigAssNumber add(BigAssNumber other) {
// This needs to be a byte by byte copy in newly allocated space, not pointer copy!
byte[] dest = value.length > other.length ? value : other.value;
// Just add each pair of numbers, like in a pencil and paper addition problem.
for(int i=0; i<min(value.length, other.value.length); i++)
dest[i]=value[i]+other.value[i];
// constructor will fix overflows.
return new BigAssNumber(dest);
}
// Fix things that might have overflowed 0,17,22 will turn into 1,9,2
private byte[] normalize(byte [] value) {
if (most significant digit of value is not zero)
extend the byte array by a few zero bytes in the front (MSB) position.
// Simple cheap adjust. Could lose inner loop easily if It mattered.
for(int i=0;i<value.length;i++)
while(value[i] > 9) {
value[i] -=10;
value[i+1] +=1;
}
}
}
}
我使用的事实是,我们在一个字节中有很多额外空间来帮助以通用方式处理额外溢出。也可以用于减法,并帮助增加一些。
答案 3 :(得分:1)
在C ++中没有简单的方法。您必须使用GNU Multiprecision之类的外部库,或使用本机支持Python等任意大整数的其他语言。
答案 4 :(得分:0)
其他海报已经为图书馆提供了链接,这些图书馆将为您完成此任务,但您似乎正在尝试将其构建为您的语言。我的第一个想法是:你确定你需要这样做吗?大多数语言都会像其他人建议的那样使用附加库。
假设您正在编写编译器并且确实需要此功能,则可以在汇编中为任意大的值实现整数运算函数。
例如,一个简单(但非最佳)的实现将数字表示为二进制编码的十进制。如果你用铅笔和纸做数学运算,算术函数可以使用与你使用的算法相同的算法。
另外,请考虑为这些大整数使用专门的数据类型。这样“正常”整数可以使用标准的32位算法。
答案 5 :(得分:0)
我首选的方法是将我当前的int类型用于32位整数(或者可能将其更改为内部长或类似,只要它可以继续使用相同的算法),然后当它溢出,将其更改为存储为bignum,无论是我自己的创建,还是使用外部库。但是,我觉得我需要检查每个算术运算的溢出,算术运算大约是2倍的开销。我怎么能解决这个问题?
答案 6 :(得分:0)
如果我实现了我自己的语言并希望支持任意长度的数字,我将使用带有进位/借位概念的目标语言。但是由于没有HLL实现这一点而没有严重的性能影响(例如异常),我肯定会在汇编中实现它。它可能需要一条指令(如在x86中的JC中)来检查溢出并处理它(如在x86中的ADC中),这对于实现任意精度的语言来说是可接受的折衷。然后我将使用一些用汇编代替常规运算符的函数,如果你可以利用重载来获得更优雅的输出,甚至更好。但我不认为生成的C ++可以作为目标语言进行维护(或意味着维护)。
或者,只需使用一个比您需要更多铃声和口哨的图书馆,并将它用于您的所有数字。
作为一种混合方法,检测汇编中的溢出并在溢出时调用库函数,而不是滚动自己的迷你库。