1000 的阶乘






4.54/5 (28投票s)
计算大数阶乘的最佳算法

引言
阶乘或正整数的乘积是最常用的数学函数(或过程)之一。许多数学计算需要大数的阶乘的精确结果,例如 1000!,以高精度找到最终结果。但问题是,没有任何编程语言具有存储如此大的数字的变量或机制。所有的编程语言和计算器都估计结果,然后将其存储为科学计数法。例如,Windows XP 的计算器显示 1000! 如下:
4.02387260077093773543702433923 e+2567
所以我决定发明一种算法来解决这个问题。
算法
您知道要计算一个数的阶乘,您应该将从 1 到它本身的所有数字相乘,例如:
1000! = 1*2*3*……*998*999*1000
没有任何编程语言中的变量可以精确地存储这个乘法的结果;除非以科学计数法存储。由于顺序乘法的巨大结果,寻找一种新的策略或机制是必要的。
在我推荐的算法中,数字不被视为一个数字,而是被视为顺序数字,其中每个数字都有自己的数值。 实际上,可以使用数字数组。 每次,第二个数字乘以第一个数字的每个数字(数组的索引),然后加上从上一次乘法运算中得到的进位数。
例如,这个过程显示了 12!
12! = 11! * 12 11! = 39916800 12! = 479001600
- 如果结果小于 10,则结果将放置在数组的单元格中。
- 如果它等于或大于 10,它将被 10 除,然后余数将被放置在数组的单元格中,商被放置在变量中,该变量将与下一次乘法运算的响应相加。
注意:请注意,所有数字都从数组的末尾存储,这与普通计算(实际计算)相同。
编程代码
声明
int numArr[3000];
int total,rem=0,count;
register int i;
在第一行中,定义了一个数组,其大小取决于阶乘的大小。 "rem
" 被定义为存储除法的余数。
最后,定义了一个名为 "i
" 的整数变量,它充当循环计数器和数组的索引,并且由于访问频繁,它被定义为寄存器。
寄存器类型修饰符告诉编译器将声明的变量存储在 CPU 寄存器中(如果可能),以优化访问。
注意:现代编译器具有良好的优化器,可以确定哪些变量应该存储在寄存器中。 当全局寄存器分配优化开启时,它们会做出自己的寄存器选择。
代码的主要部分
i=2999; //start from end of array.
numArr[2999]=1;
for(count=2;count<=1000;count++)
{
while(i>0)
{
total=numArr[i]*count+rem;
rem=0;
if(total>9)
{
numArr[i]=total%10;
rem=total/10;
}
else
numArr[i]=total;
i--;
}
rem=0;
total=0;
i=2999;
}
根据之前解释的算法,存在一个从 2 到 1000 的循环计数,每次 'count
' 的值都乘以数组的单元格并加上 'rem
',它包含来自先前乘法的进位。
最后,结果存储在 'total
' 中,然后放置在数组的单元格中。
另一种算法
起初,我为这个问题找到了另一种算法。 它基于通过连续加法来模拟乘法。 例如 20= 4*5 也是 20= (5+5+5+5)。
所以将数字放入数组中,然后将其自身加上 'X' 次。
1000! 的 X 为
X= ∑ n
n=1,2,3, … ,999,1000
注意:这种算法不如我解释的第一个算法那么优化。 而且它太枯燥了,需要几个大数组。 第二个 ZIP 文件属于此算法。
关注点
我想指出的是,该算法具有很高的计算速度,因此它使程序达到相当最佳的状态。
此算法最重要的特征之一是仅使用一个数组,而其他算法需要更多的内存(使用多个数组来模拟通过顺序和进行的乘法)。
此外,更少的编码有助于轻松理解程序,并且您可以用任何编程语言重写它。
高执行速度的原因之一是使用寄存器变量作为循环的计数器。 循环的计数器是一个对其访问最多的变量。
用法
正如我在引言中提到的,阶乘运算被用于许多数学计算中,特别是那些与需要精确阶乘结果的统计数据相关的计算。
因此,该程序可以成为任何需要阶乘方法的程序的一部分,例如统计软件。
感谢
我要感谢 Mr.Fermisk Naserzade 向我介绍这个问题,并感谢 Mr. Iraj Safa 帮助我编辑本文。