Math 计算机如何评估巨大的数字?

Math 计算机如何评估巨大的数字?,math,data-structures,Math,Data Structures,如果我在Wolfram Alpha中输入一个值,例如1234567^987878,它可以为我提供许多详细信息。这包括十进制近似值、总长度、最后一位数字等。您如何计算如此大的数字?据我所知,编程语言必须有一种特殊的数据类型才能存储数字,更不用说将其添加到其他内容中了。虽然我可以看到一个人如何处理两个非常大的数字的加法,但我看不到如何计算巨大的数字 10^2可通过重复加法计算得出。然而,像上面的例子这样的数字需要一个巨大的循环。有人能解释一下如何评估这么大的数字吗?此外,如何创建自定义大数据类型以支

如果我在Wolfram Alpha中输入一个值,例如1234567^987878,它可以为我提供许多详细信息。这包括十进制近似值、总长度、最后一位数字等。您如何计算如此大的数字?据我所知,编程语言必须有一种特殊的数据类型才能存储数字,更不用说将其添加到其他内容中了。虽然我可以看到一个人如何处理两个非常大的数字的加法,但我看不到如何计算巨大的数字


10^2可通过重复加法计算得出。然而,像上面的例子这样的数字需要一个巨大的循环。有人能解释一下如何评估这么大的数字吗?此外,如何创建自定义大数据类型以支持C#中的大数字?例如,

通常有一些库为任意大的整数提供bignum数据类型(例如,将数字
k*n...(k+1)*n-1,k=0..
映射到大小为
n
的机器字,重新定义算术运算)。对于c#,您可能会感兴趣

幂运算可以递归分解:

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

还有一些数论结果产生了特殊的算法来确定大数的性质,而无需实际计算它们(准确地说:它们的全十进制展开)。

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

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
后面的k位是通过执行mod 10^k的幂运算来计算的,这可以防止中间结果变得太大


近似值将使用(软件)浮点实现进行计算,该实现有效地将a^(987878 log_a(1234567))评估为某个数字a的某个固定精度,从而使算术计算结果良好(通常为2或e或10)。这也避免了在任何时候实际处理数百万位的需要。

我认为答案的一部分在于问题本身:)要存储这些表达式,可以像科学记数法那样分别存储基数(或尾数)和指数。扩展到这一点,您不可能完全计算表达式并存储如此大的数字,尽管理论上可以预测后续表达式的某些属性。我将带您浏览您提到的每一处房产:

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

  • 这很容易,你可以自己做

  • 可通过对数获得位数:
  • 我们可以计算
    (A=1234567;B=987878)
    ,在我们的例子中

     `B * log(A, 10) = 98787878 * log(1234567, 10) = 601767807.4709646...`
    
    整数部分+1
    601767807+1
    =601767808)是位数

  • 首先,比如说,五位数也可以通过对数得到; 现在我们应该分析这个过程的分数部分

    B*log(A,10)
    987878*log(1234567,10)
    601767807.4709646…

    f=0.4709646…

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

  • 最后,例如,可以获得五位数字作为相应的余数:

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

    A雷姆10^5=1234567雷姆10^5=34567

    A^B雷姆10^5=((A雷姆10^5)^B)雷姆10^5=(34567^987878)雷姆10^5=45009

    最后五位数字为45009

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

  • 最后


    1234567^98787878=29577…45009(601767808位)

    有许多用于此的库,python内置了此功能。您似乎主要关心这些数字的大小,以及像示例中的指数那样进行计算所需的时间。所以我会解释一下

    表示法 您可以使用数组来保存大数字的所有数字。更有效的方法是使用32位无符号整数数组并存储大数的“32位块”。您可以将这些数据块视为数字系统中具有2^32个不同数字或字符的单个数字。我在8位Atari800上使用了一个字节数组来实现这一点

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

    在实践中 它是
     `B * log(A, 10) = 98787878 * log(1234567, 10) = 601767807.4709646...`