Option Explicit
Dim incl As Boolean, starttime As Long
Private Function cacl(num As Long) As String
Dim flag As Long, numlen As Long, last As Long
Dim x As Long, k As Long, i As Long, m As Long, n As Long, j As Long
Dim result() As Long, tmp1() As Long, tmp2() As Long, s() As String
numlen = 1
ReDim result(1 To numlen)
result(1) = 1
x = 0
Do While incl = True And x < num
x = x + 1
flag = x
i = 0
Do
i = i + 1
last = flag Mod 10 '取出被乘数的最后一位
flag = flag \ 10 '去掉乘数的最后一位
tmp1 = result
n = 0
For k = 1 To numlen
m = tmp1(k) * last + n '用每一位数与上次结果数组中的每个数相乘并加上进位的数
tmp1(k) = m Mod 10 '取出最后一位并加入临时结果数组
n = m \ 10 '两个小于10的数相乘最多两位,这里取出进位数
Next
If n > 0 Then '处理最后一个进位数
ReDim Preserve tmp1(1 To numlen + 1)
tmp1(numlen + 1) = n
End If
If i = 1 Then
tmp2 = tmp1 '用第二个临时数组保存每次个位数乘出来的结果
Else
n = 0 '下面把本次乘出来的临时数组与上次乘出来的临时结果错位相加(就象乘法算式一样)。
j = UBound(tmp1) + i - 1
If UBound(tmp2) < j Then ReDim Preserve tmp2(1 To j)
For k = i To j
m = tmp2(k) + tmp1(k - i + 1) + n
tmp2(k) = m Mod 10
n = m \ 10
Next
If n > 0 Then
ReDim Preserve tmp2(1 To j + 1)
tmp2(j + 1) = n
End If
End If
Loop While flag > 0
numlen = UBound(tmp2)
result = tmp2
Label1 = x '下面三句可用Label1与Label2计算进度,并及时更新
Label2 = numlen
Label3 = Timer - starttime
DoEvents
Loop
k = UBound(result)
ReDim s(1 To k)
For i = k To 1 Step -1
s(k - i + 1) = CStr(result(i))
Next
cacl = Join(s, "")
End Function
Private Sub Command1_Click()
Dim i As Long
If incl = False Then
Command1.Caption = "看看结果"
incl = True
starttime = Timer
Text1 = cacl(CLng(Text2))
Else
incl = False
Command1.Caption = "再算一次"
End If
End Sub
公用模块中定义函数:f(n,m) '整数N包含整数M的因子的个数
Function f(n As Long, m As Long) As Long
f = 0
For k = 0 To n
If Int(n / m ^ k) = n / m ^ k And Int(n / m ^ (k + 1)) <> n / m ^ (k + 1) Then
f = k
Exit Function
End If
Next
End Function
然后调用:
Private Sub Command1_Click()
Dim i As Long
s2 = 0
For i = 1 To 50
s2 = s2 + f(i, 2)
Next
s5 = 0
For i = 1 To 50
s5 = s5 + f(i, 5)
Next
s = IIf(s2 < s5, s2, s5)
Print s
公用模块中定义函数:f(n,m) '整数N包含整数M的因子的个数
Function f(n As Long, m As Long) As Long
f = 0
For k = 0 To n
If Int(n / m ^ k) = n / m ^ k And Int(n / m ^ (k + 1)) <> n / m ^ (k + 1) Then
f = k
Exit Function
End If
Next
然后调用:
Private Sub Command1_Click()
Dim i As Long
s2 = 0
For i = 1 To 50
s2 = s2 + f(i, 2)
Next
s5 = 0
For i = 1 To 50
s5 = s5 + f(i, 5)
Next
s = IIf(s2 < s5, s2, s5)
Print s
Function Calc(ByVal m As Integer, ByVal n As Integer) As String
Dim ret As String
Dim i As Integer
Dim j As Double
Dim Pos1 As Integer
Dim Pos2 As Integer
Dim ZeroNum As Integer
Dim SubZeroNum As Integer
j = 1
For i = m To n
j = i * j
Next
ret = Str(j)
Pos2 = InStr(ret, "+")
If Pos2 <> 0 Then
Pos1 = InStr(ret, ".")
If Pos1 <> 0 Then
ZeroNum = Val(Mid(ret, Pos2 + 1, Len(ret) - Pos2))
SubZeroNum = Len(Mid(ret, Pos1 + 1, Pos2 - Pos1 - 2))
ZeroNum = ZeroNum - SubZeroNum '最终有效的'0'个数
ret = Format(ret, Replace(Space(ZeroNum), " ", "#"))
End If
End If
Calc = ret
End Function
Private Sub Command1_Click()
Debug.Print Calc(1, 50)
End Sub
重新写以下,计算尾 0 个数代码有错:
逐个数字分析,含有几个因数 5 和几个因数 2。取其中较小的,就是 0 的个数。
fives=0
twos=0
for i = 1 to 50
tmp = i
do util tmp mod 5 '*****************
tmp = tmp / 5
fives=fives + 1
loop
do until tmp mod 2
tmp = tmp / 2
twos=twos + 1
loop '******************
next i
if fives > twos then
msgbox "you'll get " & twos & " 0's."
zeros = twos
else
msgbox "you'll get " & fives & " 0's."
zeros = fives
endif
所以在计算尾 0 时应保留 1 个变量(例如 zeros),上面计算中间零时:
fives = zeros
twos =zeros
......
do until x mod 2 and twos
x = x / 2
twos = twos - 1
loop
do until x mod 5 and fives
x = x / 5
fives = fives - 1
loop
......
将所有乘数中的 2 和 5 的因子去掉,因为它们对中间 0 没有贡献。
dim p as currency
p = 1
for i=1 to 50
x = i
do until x mod 2
x = x / 2
loop
do until x mod 5
x = x / 5
loop
p = p * x
next i
strR = cstr(p)
msgbox len(strR) - len(replace(strR, "0","")) & " 0's"
如果只要求 0 的个数,就没有必要实际的大数计算。
逐个数字分析,含有几个因数 5 和几个因数 2。取其中较小的,就是 0 的个数。
fives=0
twos=0
for i = 1 to 50
if i mod 5 = 0 then fives=fives + i/5
if i mod 2 = 0 then twos=twos + i/2
next i
if fives > twos then
msgbox "you'll get " & twos & " 0's."
else
msgbox "you'll get " & fives & " 0's."
endif