莫依等所有能解决问题的高手请进,大数相乘的问题

greentest 2005-07-01 08:50:13
1*2*3*4*5*...........49*50 如何才能得到精确的结果?对结果不能用科学计算法表示,主要是得出最后结果有几个0。
...全文
500 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
jxgzay 2005-07-01
  • 打赏
  • 举报
回复

1*2*3*。。。49*50 12
1*2*3。。。499*500 124
1*2*3*...*4999*5000 是1249个0
1*2*3*...*49999*50000 12499
1*2*3*。。。*499999*500000 124999
非常有规律!

还想懒够 2005-07-01
  • 打赏
  • 举报
回复
如果还需要获取得到几个0,可再分析Text1中的字符串
还想懒够 2005-07-01
  • 打赏
  • 举报
回复
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


一个CommandButton,二个TextBox,三个Label控件

TextBox2输入需要计算阶乘的最大值,在Text1中反映出结果.可计算1000位以上的阶乘代码
jxgzay 2005-07-01
  • 打赏
  • 举报
回复
公用模块中定义函数: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

End Sub

答案是12个0


1*2*3*4*...*499*500呢
答案是124个0
jxgzay 2005-07-01
  • 打赏
  • 举报
回复
公用模块中定义函数: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

End Sub

答案是12个0


1*2*3*4*...*499*500呢
答案是124个0



End Function


唐古拉山 2005-07-01
  • 打赏
  • 举报
回复

我的函数是通用的

结果的结果比Google的要精确一些 ^_^





唐古拉山 2005-07-01
  • 打赏
  • 举报
回复
'结果:
'30414093201713400000000000000000000000000000000000000000000000000

这个结果后面有 50 个0


唐古拉山 2005-07-01
  • 打赏
  • 举报
回复
我写的函数:

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

'用程序计算结果:
'3.04140932017134E+64
'结果:
'30414093201713400000000000000000000000000000000000000000000000000



'用Google计算
'1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 * 24 * 25 * 26 * 27 * 28 * 29 * 30 * 31 * 32 * 33 * 34 * 35 * 36 * 37 * 38 * 39 * 40 * 41 * 42 * 43 * 44 * 45 * 46 * 47 * 48 * 49 * 50 = 3.04140932 × 10的64次方
'3.04140932 ×10的64次方





daisy8675 2005-07-01
  • 打赏
  • 举报
回复
30414093201713378043612608166064768844377641568960512000000000000

是不是这个,of123验证下12个0

我去baidu转换发现baidu的哪个破烂计算算出了一个72. 多少,真亏他们的代码人员了...
of123 2005-07-01
  • 打赏
  • 举报
回复
我喜欢这样的问题。真正考验智商。不仅仅是 Copy 代码的功夫。
of123 2005-07-01
  • 打赏
  • 举报
回复
重新写以下,计算尾 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
cxbkkk 2005-07-01
  • 打赏
  • 举报
回复
mark
of123 2005-07-01
  • 打赏
  • 举报
回复
greentest(淡) :
考虑了。10 除以 2 和 5 以后就没有了。我考虑的是因子。

另,上面计算中间 0 的代码有一个疏漏,删除 2 和 5 的因子数应当等于产生尾 0 的个数。

所以在计算尾 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
......
daisy8675 2005-07-01
  • 打赏
  • 举报
回复
可以把1-50缩小的1-10

1*10的结果是 3628800

分解成2*4*6*8*10= 3840 --->1个0

分解3*5*7*9= 945

再分解3*7*9= 189
根据上面的分解可以知道,要得出0的结果,只可能是5和其倍数和双数去乘

意思也就是3,7,9包括11,13,17....这几个数字是不可能出现。所以可以过滤掉这些数据
1~10中间产生0的可能是2,4,6,8,10,5-->产生2个0


这也就是问你到底要取几个0的意思

这只是我的一个简单思路。不过还没验证,现在忙,中午再验证下。

数学题蛮有意思的,不过具体结果还是等我呆会看看E+64是多少再说,寒,真的忘数学了-_-###
of123 2005-07-01
  • 打赏
  • 举报
回复
如果还需要计算中间的 0, 可以先如上计算出结尾的 0, 然后简化计算:

将所有乘数中的 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"
greentest 2005-07-01
  • 打赏
  • 举报
回复
for of123() ( ) 信誉:125

你还没考虑10,20,30等 0的个数,另外你的结果也不对,不过你的思路是非常好的,感谢
greentest 2005-07-01
  • 打赏
  • 举报
回复
晕了,还真没想过有那么复杂,不过我是想知道最后有几个0,对应你的是2个0
of123 2005-07-01
  • 打赏
  • 举报
回复
如果只要求 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
daisy8675 2005-07-01
  • 打赏
  • 举报
回复
楼主是不是要最后有几个0还是结果有几个0

比如30700这个数字

你想得到2个0还是3个0
daisy8675 2005-07-01
  • 打赏
  • 举报
回复
3.04140932017134E+64

已经超过28位了,不能用cdec转了,我得找找科学计算法是怎么转的,数学快丢完了,哈
加载更多回复(17)

7,762

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧