【问题标题】:Represent Integers with 2000 or more digits [duplicate]表示具有 2000 位或更多位的整数 [重复]
【发布时间】:2015-07-23 10:39:17
【问题描述】:

我想编写一个程序,它可以计算超过 2000 或 20000 位的整数(对于 Pi 的小数)。我想用 C++ 做,没有任何库! (没有大整数,提升,...)。任何人都可以提出一种方法吗?以下是我的想法:

  • 使用const char*,用于保存整数的数字;

  • 代表数字像


( (1 * 10 + x) * 10  + x )...

【问题讨论】:

  • 我很想为每个数字使用uint8_t。不是特别对内存友好,但会使算术运算易于处理。或者,考虑更难的二进制编码十进制 (BCD) 表示法。
  • 整数 对 Pi 没有用处。为什么你不想要 lib?
  • 2 ) 因为我在练习 C++ 和数学:)
  • 我没说你不应该。但是如果你要问其他人你应该怎么做,你不妨看看过去是怎么做的,因为这是人们在你自己的图书馆里会给你的建议。
  • bignums 上阅读大量论文和书籍。这是一门数学难题,而且你也有编程问题。编写一个有竞争力的 bignum 库可能需要你数十年的时间。

标签: c++ integer


【解决方案1】:

显而易见的答案是这样的:

class integer {
    bool negative;
    std::vector<std::uint64_t> data;
};

其中数字表示为符号位和(无符号)基数 2**64 值。

这意味着你的号码的绝对值是:

数据[0] + (数据[1]

或者,换句话说,您将您的数字表示为一个 little-endian 位串,其中包含您的目标机器可以合理使用的单词大小。我选择了 64 位整数,因为您可以通过这种方式(在 x64 机器上)最大限度地减少单个字操作的数量。

要实现加法,您需要使用您在小学时学到的概念:

  a           b
+ x           y
------------------
 (a+x+carry) (b+y reduced to one digit length)

减少(模 2**64)自动发生,进位只能是 0 或 1。剩下的就是检测进位,这很简单:

bool next_carry = false;
if(x += y < y) next_carry = true;
if(prev_carry && !++x) next_carry = true;

减法可以类似地使用借位来实现。 请注意,接近例如性能的任何地方libgmp 是……不太可能。

【讨论】:

  • 在我看来,使用补码形式会更加明显。
  • 您建议使用 2^64 作为基础。那你可以在没有汇编的情况下实现进位乘法吗?
  • 为了容纳像 pi 这样的数字,这还需要数据成员来规定小数点的位置。
  • @stgatilov 是的 - 您将它们视为两个 32 位数字并进行微小的学校乘法。
  • 您能简单说明一下如何重载 + 和 = 运算符吗?
【解决方案2】:

长整数通常由数字序列表示(参见positional notation)。为方便起见,使用little endian 约定:A[0] 是最低位,A[n-1] 是最高位。在一般情况下,对于 base 的某个值,您的数字等于 sum(A[i] * base^i)

base 的最简单值是 10,但效率不高。如果你想经常打印你的答案给用户,你最好使用十的幂作为base。例如,您可以使用 base = 10^9 并将所有数字存储在 int32 类型中。如果您想要最大速度,那么最好使用二次方基地。例如,base = 2^32 是 32 位编译器的最佳基础(但是,您需要汇编才能使其最佳工作)。

负整数有两种表示方式,第一种是将整数存储为符号+数字序列。在这种情况下,您必须自己处理所有带有不同标志的情况。另一种选择是使用complement form。它可用于二的幂和十的幂。

由于序列的长度可能不同,最好将数字序列存储在std::vector中。在这种情况下不要忘记删除leading zeroes。另一种解决方案是始终存储固定数量的数字(固定大小的数组)。

这些操作以非常简单的方式实现:就像你在学校做的那样 =)

P.S. 或者,由于CRT,每个整数(有界长度)都可以通过其提醒一组不同的素数模块来表示。这种表示仅支持有限的一组操作,如果您想打印它,则需要进行非平凡的转换。

【讨论】:

  • 不,bignum 算术运算并不简单。他们正在使用非常困难但高效的算法(比高中的要好得多)。 Bignum 算法真的很难!
  • @BasileStarynkevitch 实际上,最快的 bignum 库使用 FFT 进行乘法等。但是,简单的操作很容易实现并且效果很好。这对OP来说应该足够了。此外,我非常怀疑内置 BigInt 是否使用 Java 中的任何 FFT。
猜你喜欢
  • 1970-01-01
  • 2018-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 2015-04-24
  • 1970-01-01
  • 2013-10-15
相关资源
最近更新 更多