从10 ^ x到2 ^ x的大整数基数/基数转换

时间:2011-06-06 22:40:05

标签: algorithm math gmp bigint

前言

我正在通过编写和完善我自己的BigInt库来学习计算机数学。到目前为止,我的第一个化身将一个基数为10的数字存储在向量的连续元素中。它可以以任意精度相乘和相加。我希望通过转换为base 2 ^ x来使用标准C ++数据类型中可用的所有空间来加快速度。

信息

我正在读取基数10中stdin的1000位或更多位数,我希望将它们转换为基数2 ^ x,因此我可以将它们轻松存储在标准C ++数据类型之一的数组或向量中,可能是unsigned int。关于如何进行基本转换,使用余数方法重复除法,我只有一个想法。以下是一些描述该方法的C ++代码:

vector<int> digits;
while(num!=0) {
   int mod = num%base;
   num = num/base;
   digits.push_back(mod);
}

难题

我遗失的一些事情是,与余数的划分是否是在大整数上进行基数转换的正确方法。我试过看 GMP库是如何做到的。 gmp/mpn/generic/set_str.c是相关的c源文件,其中“魔术”发生,但我不确定那里发生了什么。 Matt McCutchen的 BigInt 似乎使用了余数方法的重复除法。如果我使用这种方法,我基本上需要编写两个版本的BigInt类,一个用于Base10,另一个用于Base2 ^ x。

结论

  • 就将字符串中的大数字转换为32位字数组的正确步骤提供建议。
  • 帮助我了解GMP如何将字符串转换为32位字的数组,而无需涉及多层抽象。

使用4位字长

的示例

我们要存储的号码(显然是小号):123456789

无符号字符的范围为0-255,如果我们想要将数字拆分并将其存储在向量中,我们可以采用以下三种方式之一:

  • 作为基数10,我们的向量看起来像:[1,2,3,4,5,6,7,8,9]
    • 这是我第一次实现时矢量的样子。
  • 作为基数100,我们的向量看起来像:[1,23,45,67,89]
    • 易于从基数10转换为基数100,具有ciel(base10 / 2中的数字)元素。
  • 作为基数256,我们的向量看起来像:[7,91,205,21]

显然,第三种解决方案对于内部表示来说是最理想的,而且正是我想要达到的目的。

3 个答案:

答案 0 :(得分:6)

一旦你有乘法并添加适用于bigint库的函数,将字符串转换为bigint本身就是简单的。转换结果为零。对于您处理的每个数字(从左到右),将前一个结果乘以10并添加新数字的值(使用bigint乘法并添加函数)。

答案 1 :(得分:1)

通常,要将一个基数转换为另一个基数(从最高有效数字到最低数字),算法如下:

output = 0
foreach digit in digits:
    output = output * base + digit

以相反的顺序,它是以下内容:

output = 0
multiplier = 1
foreach digit in digits:
    output = output + multiplier * digit
    multiplier = multiplier * base

您可以使用此数学递归使用bigint库来确定如何存储数字。通过这个,我的意思是你需要实现BigInt * BigInt和BigInt + BigInt,所以这就是你如何转换基数。这不是最有效的方式,但它比分裂快得多。

答案 2 :(得分:0)

FryGuy帖子中没有提到的一点是,在该方法中,算法必须在您将转换为的基础上执行,而用作乘数的基数是相同的作为原始号码的基础;您不再需要的基数或您要转换的基础来自

整数上有两个基数转换公式。 (1)使用基数B,我们将转换为(目的地基数),作为重复除数,加上在基数b中完成的算术,其中b是基数转换来自 。 (2)另一方面,使用基数b作为我们正在转换的数字的乘数,它恰好位于相同的基数b中,并且在基数B中进行算术运算。

(1)公式使用B作为参数并在base b中进行算术

(2)公式使用b作为参数并在基数B中进行算术

这是出于knuth,第2卷,4.4基数转换