大数阶乘的计算(五)

原创 2004年06月07日 09:59:00

很难想象只要改动几句代码就可以大幅提高执行的效率,在前几篇文章中我写了几种大数阶乘的算法(http://www.csdn.net/Develop/read_article.asp?id=28306http://www.csdn.net/Develop/read_article.asp?id=28308http://www.csdn.net/Develop/read_article.asp?id=28432),效率都比较低。今日看了homezj(http://www.csdn.net/Develop/article/28/28584.shtm )的代码,很受启发,优化如下:

 

<一>按每四位进行一次计算:

Sub calcfactorial(ByVal num As Long, Optional ByRef factorial As String)

Dim numlen As Long, last As Long, i As Long, j As Long, temp As Long

Dim result() As Long, s() As String, stime As Double
numlen = 1
stime = Timer
ReDim result(1 To numlen)
result(1) = 1
i = 0
Do While i < num
i = i + 1
   last = 0
   For j = 1 To numlen
        temp = result(j) * i + last
        result(j) = temp Mod 10000
        last = temp / 10000
   Next
   Do While Not last = 0
           ReDim Preserve result(1 To numlen + 1)
            result(numlen + 1) = last Mod 10000
            last = last / 10000
           numlen = UBound(result)
  Loop
Loop
ReDim s(1 To numlen)
For i = 2 To numlen
s(i) = Format(result(numlen + 1 - i), "0000")
Next
s(1) = result(numlen)

factorial = Join(s, "")
Debug.Print num & "! : 用时 "; Timer - stime & " 秒, 结果 " & Len(factorial) & " 位,前5位为 " & Left(factorial, 5)
'Debug.Print factorial
Erase s
Erase result
End Sub

Private Sub Command1_Click()
For i = 1 To 20
calcfactorial i * 1000
Next
End Sub

输出结果:
'1000! : 用时 7.82500000059372E-02 秒, 结果 2568 位,前5位为 40238
'2000! : 用时 .391499999997905 秒, 结果 5736 位,前5位为 33162
'3000! : 用时 .968875000005937 秒, 结果 9131 位,前5位为 41493
'4000! : 用时 1.78174999999464 秒, 结果 12674 位,前5位为 18288
'5000! : 用时 2.84412500000326 秒, 结果 16326 位,前5位为 42285
'6000! : 用时 4.20387500000652 秒, 结果 20066 位,前5位为 26839
'7000! : 用时 5.84387500000594 秒, 结果 23878 位,前5位为 88420
'8000! : 用时 7.75012500000594 秒, 结果 27753 位,前5位为 51841
'9000! : 用时 9.98512500000652 秒, 结果 31682 位,前5位为 80995
'10000! : 用时 12.5160000000033 秒, 结果 35660 位,前5位为 28462
'11000! : 用时 15.2818750000006 秒, 结果 39681 位,前5位为 31624
'12000! : 用时 18.4063750000059 秒, 结果 43742 位,前5位为 12018
'13000! : 用时 21.7975000000006 秒, 结果 47838 位,前5位为 77871
'14000! : 用时 25.5320000000065 秒, 结果 51969 位,前5位为 13864
'15000! : 用时 29.5627499999973 秒, 结果 56130 位,前5位为 27465
'16000! : 用时 33.90625 秒, 结果 60320 位,前5位为 51187
'17000! : 用时 38.5786249999946 秒, 结果 64538 位,前5位为 13797
'18000! : 用时 43.5477499999979 秒, 结果 68781 位,前5位为 13525
'19000! : 用时 48.84375 秒, 结果 73048 位,前5位为 18269
'20000! : 用时 54.4375 秒, 结果 77338 位,前5位为 18192

 

<二>按每五位进行一次计算:

Sub calcfactorial(ByVal num As Long, Optional ByRef factorial As String)

Dim numlen As Long, last As Long, i As Long, j As Long, temp As Long

Dim result() As Long, s() As String, stime As Double

numlen = 1
stime = Timer
ReDim result(1 To numlen)
result(1) = 1
i = 0
Do While i < num
i = i + 1
   last = 0
   For j = 1 To numlen
        temp = result(j) * i + last
        result(j) = temp Mod 100000
        last = temp / 100000
   Next
   Do While Not last = 0
           ReDim Preserve result(1 To numlen + 1)
            result(numlen + 1) = last Mod 100000
            last = last / 100000
           numlen = UBound(result)
  Loop
Loop
ReDim s(1 To numlen)
For i = 2 To numlen
s(i) = Format(result(numlen + 1 - i), "00000")
Next
s(1) = result(numlen)

factorial = Join(s, "")
Debug.Print num & "! : 用时 "; Timer - stime & " 秒, 结果 " & Len(factorial) & " 位,前5位为 " & Left(factorial, 5)
'Debug.Print factorial
Erase s
Erase result
End Sub

Private Sub Command1_Click()
For i = 1 To 20
calcfactorial i * 1000
Next
End Sub

输出结果:

1000! : 用时 6.26250000059372E-02 秒, 结果 2568 位,前5位为 40238
2000! : 用时 .297124999997322 秒, 结果 5736 位,前5位为 33162
3000! : 用时 .782000000006519 秒, 结果 9131 位,前5位为 41493
4000! : 用时 1.421875 秒, 结果 12674 位,前5位为 18288
5000! : 用时 2.26612499999464 秒, 结果 16326 位,前5位为 42285
6000! : 用时 3.79700000000594 秒, 结果 20066 位,前5位为 26839
7000! : 用时 4.65625 秒, 结果 23878 位,前5位为 88420
8000! : 用时 6.21899999999732 秒, 结果 27753 位,前5位为 51841
9000! : 用时 8.375 秒, 结果 31682 位,前5位为 80995
10000! : 用时 9.98512500000652 秒, 结果 35660 位,前5位为 28462
11000! : 用时 12.2351250000065 秒, 结果 39681 位,前5位为 31624
12000! : 用时 14.6882500000065 秒, 结果 43742 位,前5位为 12018
13000! : 用时 17.4696249999979 秒, 结果 47838 位,前5位为 77871
14000! : 用时 20.4071249999979 秒, 结果 51969 位,前5位为 13864
15000! : 用时 23.625 秒, 结果 56130 位,前5位为 27465
16000! : 用时 27.0783749999973 秒, 结果 60320 位,前5位为 51187
17000! : 用时 30.875 秒, 结果 64538 位,前5位为 13797
18000! : 用时 34.8131250000006 秒, 结果 68781 位,前5位为 13525
19000! : 用时 39.0320000000065 秒, 结果 73048 位,前5位为 18269
20000! : 用时 43.5783749999973 秒, 结果 77338 位,前5位为 18192

 

可以看出,按五位五位的进行计算效率较高。但有一点必须明确,末尾多个“0”参与运算浪费了时间和内存,所以缩短运行时间仍有相当大的空间。

N阶乘MOD P

#include using namespace std; int mod(long long int n,long long int p) { if (n == 0) return 1; ...
  • dherorunner
  • dherorunner
  • 2017年03月10日 20:31
  • 441

计算大数阶乘--Fortran版

本文给出一个使用Fortran语言的计算大数阶乘的程序,该程序可以计算出1-21万之间的数的阶乘。...
  • liangbch
  • liangbch
  • 2012年06月05日 10:52
  • 3933

大数整除(大数mod)

Description 定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍。当且仅当差是17的倍数时,原数也是17的倍数 。 例如,34是17的倍数,因为3-20=-1...
  • bmamb
  • bmamb
  • 2016年04月30日 17:41
  • 961

大数阶乘取模

水了90分。。。 如果不会正解的话,直接暴力拿分,无脑暴力可以拿到90分 正解分块打表暴力就是直接求阶乘然后取模。。。 加一个比较有用的特判:如果n>=p,那么n的阶乘的因子中一定有p,n的阶乘膜...
  • qq_35798459
  • qq_35798459
  • 2017年10月07日 10:22
  • 421

大数阶乘的计算(五)

很难想象只要改动几句代码就可以大幅提高执行的效率,在前几篇文章中我写了几种大数阶乘的算法(http://www.csdn.net/Develop/read_article.asp?id=28306,h...
  • northwolves
  • northwolves
  • 2004年06月07日 09:59
  • 1609

100以内的阶乘计算方法

阶乘计算虽然可以通过循环、递归或者使用静态变量等方法实现,但是这些方法仅限于结果较小的情况。100的阶乘有158位,显然在使用C++时很难保证直接计算时不会产生溢出。 这里可以采用数组的方式存储计算...
  • lsj308
  • lsj308
  • 2014年12月12日 23:10
  • 1487

计算大数阶乘--Java版

本文给出Java语言版的计算大数阶乘的程序,本文使用动态数组的存储计算过程的中间结果和最终结果。每个short型数组元素表示4位10进制数。...
  • liangbch
  • liangbch
  • 2012年06月01日 09:41
  • 3622

大数阶乘的计算(五)

对计算(四)我总觉得没有发挥Long类型的最大潜力,一定是我的算法还有改进余地。经进一步推敲,终于又有了突破,速度一下子又提高 4 倍!同一台机器上10000!用时9.8秒,而且大胆的算了一次2000...
  • homezj
  • homezj
  • 2004年06月07日 16:37
  • 1922

Excel VBA 编程练习

根据表单名称从work查找
  • lsj308
  • lsj308
  • 2014年04月30日 22:27
  • 1431

如何计算数据组合在全排序组合中的行值

VBA计算数据组合在全排序组合中的行值
  • northwolves
  • northwolves
  • 2010年07月06日 21:12
  • 2376
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:大数阶乘的计算(五)
举报原因:
原因补充:

(最多只允许输入30个字)