计算机如何评估大量数字?

时间:2013-08-20 11:34:51

标签: math data-structures

如果我输入一个值,例如1234567 ^ 98787878到Wolfram Alpha,它可以为我提供一些细节。这包括十进制近似,总长度,最后一位数等。您如何评估这么大的数字?据我所知,编程语言必须有一个特殊的数据类型才能存储数字,更不用说将其添加到其他内容中。虽然我可以看到人们如何接近增加两个非常大的数字,但我看不出有多大的数字被评估。

10 ^ 2可以通过重复添加来计算。然而,诸如上述示例之类的数字将需要巨大的循环。有人可以解释如何评估这么大的数字吗?另外,有人如何创建自定义大型数据类型以支持C#中的大数字?

5 个答案:

答案 0 :(得分:11)

嗯,这很容易,你可以自己完成

  1. 位数可以通过 logarithm 获得:

    A^B = 10 ^ (B * log(A, 10))

    以来

    我们可以在

    的情况下计算(A = 1234567; B = 98787878)

    B * log(A, 10) = 98787878 * log(1234567, 10) = 601767807.4709646...

      

    integer part + 1 (601767807 + 1 = 601767808 是位数

  2. 首先,比方说, 5 digits 也可以通过 logarithm 获得;  现在我们应该分析

    的小数部分

    B * log(A, 10) = 98787878 * log(1234567, 10) = 601767807.4709646...

    f = 0.4709646...

      

    第一个数字为10^f(已删除小数点)= 29577 ...

  3. 最后,比方说, 5 digits 可以作为相应的余数获取:< / p>

    最后五位= A^B rem 10^5

    A rem 10^5 = 1234567 rem 10^5 = `34567

    A ^ B rem 10 ^ 5 **=**((A rem 10 ^ 5)^ B)rem 10 ^ 5 **=** (34567 ^ 98787878)rem 10 ^ 5 = 45009 `

      

    最后五位是 45009

    您可能会发现BigInteger.ModPow(C#)在这里非常有用

  4. 最后

    1234567 ^ 98787878 = 29577 ... 45009(601767808位)

答案 1 :(得分:3)

通常存在为任意大整数提供bignum数据类型的库(例如,将数字k*n...(k+1)*n-1, k=0..<some m depending on n and number magnitude>映射到大小为n的机器字,重新定义算术运算)。对于c#,您可能对BigInteger感兴趣。

取幂可以递归分解:

pow(a,2*b)   = pow(a,b) * pow(a,b);
pow(a,2*b+1) = pow(a,b) * pow(a,b) * a;

还有一些数论结果已经生成特殊算法来确定大数的属性而不实际计算它们(确切地说:它们的完整十进制扩展)。

答案 2 :(得分:3)

要计算有多少位数,可以使用以下表达式:

decimal_digits(n) = 1 + floor(log_10(n))

这给出了:

decimal_digits(1234567^98787878) = 1 + floor(log_10(1234567^98787878))
                                 = 1 + floor(98787878 * log_10(1234567))
                                 = 1 + floor(98787878 * 6.0915146640862625)
                                 = 1 + floor(601767807.4709647)
                                 = 601767808

通过使用取幂mod 10 ^ k来计算尾随k个数字,这使得中间结果不会变得太大。

使用(软件)浮点实现来计算近似值,该实现有效地评估^(98787878 log_a(1234567))到某个数字a的某个固定精度,这使得算术运算良好(通常为2或e或10)。这也避免了在任何时候实际使用数百万个数字的需要。

答案 3 :(得分:0)

这有很多库,并且在python的情况下内置了该功能。您似乎主要关注此类数字的大小以及执行计算所需的时间,例如示例中的指数。所以我会解释一下。

<强>表示 您可以使用数组来保存大数字的所有数字。一种更有效的方法是使用32位无符号整数数组并存储大数字的“32位块”。您可以将这些块视为具有2 ^ 32个不同数字或字符的数字系统中的单个数字。我在当天的8位Atari800上使用了一个字节数组来执行此操作。

做数学 显然,您可以通过循环所有数字并将一个数组的元素添加到另一个数组并跟踪进位来添加两个这样的数字。一旦你知道如何添加,你就可以编写代码来通过乘以数字进行“手动”乘法,并将结果放在正确的位置并添加很多 - 但软件可以很快地完成所有这些操作。比在纸上手动使用的算法还要快。纸张乘法是O(n ^ 2),其他方法是O(n * log(n))。至于指数,你当然可以乘以相同的数字数百万次,但这些乘法中的每一次都将使用前面提到的乘法函数。有更快的方法可以进行取幂,这需要更少的乘法。例如,你可以通过计算(((x ^ 2)^ 2)^ 2)^ 2计算x ^ 16,它只涉及4个实际(大整数)乘法。

在实践中 尝试自己编写这些函数既有趣又有教育意义,但在实践中,您需要使用已经过优化和验证的现有库。

答案 4 :(得分:-1)

我认为答案的一部分在于问题本身:)要存储这些表达式,您可以单独存储基数(或尾数)和指数,就像科学记数法一样。扩展到那个,你不可能完全评估表达式并存储这么大的数字,但是,理论上你可以预测后续表达式的某些属性。我将带您了解您谈到的每个属性:

  1. 十进制逼近:可以通过评估简单的对数值来计算。
  2. 表达式a ^ b的总位数,可以通过公式计算 数字=地板函数(1 + Log10(a ^ b)),其中floor函数是小于数字的最接近的整数。对于例如10 ^ 5中的位数为6.
  3. 最后的数字:这些可以通过线性增加的指数的表达形成算术级数的事实来计算。对于例如在单位;对于7 ^ x的指数重复7,9,3,1。因此,您可以计算出如果x%4为0,则最后一位为1。 有人可以为大数字创建自定义数据类型,我不能说,但我相信,这个数字不会被评估和存储。