帮帮忙,给个算法

gflion 2004-03-30 05:34:53
要求是这样的,随机取一个100000以下的数字a,然后要求产生1个随机数字b,b要可以被a整除,比如随机产生了一个88888(a),然后随机取出一个能被其整除的22(b)

我原来的算法是for i=1;i<=a; i++,然后一个一个试,将结果放进一个数组,然后在这个数组里随机取一个,这样实在太傻了,可是又想不出更好的办法,哪位能帮帮忙?
...全文
79 39 打赏 收藏 转发到动态 举报
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
lsftest 2004-04-03
  • 打赏
  • 举报
回复
你那红外控制搞的怎么样了?
=================================
不太顺利,红外接收那部分应该没有什么问题了,但我的目的是用来控制另一个程序:我有一张ati的电视卡可以接收电视,在它的播放程序里有一个按钮,点击就可以换频道,或者按“+”键也可以,我就是想用遥控控制它的频道转换,那么就可以躺在床上看电视了(懒人本色,呵呵)。。问题是不知道怎么往按钮发消息。。找到了按钮的hwnd,向它sendmessage,keydown,keyup,wm_char,都试过了,都没有反应。。用sendkeys “+”也不行。。。用myspy跟踪它接收的消息。。。然后按“+”键,频道是变了,但myspy却显示那个按钮没有接收到这个按钮消息,真不知是哪个窗口接收了去。。。郁闷ing。。。。

今天升星了,高兴的啊。
====================
恭喜恭喜,高人就是不一样,我在csdn呆了一年多才蹭了五个裤衩,惭愧啊。。。。。
顺带问一句,要多少分才能升星??
pigsanddogs 2004-04-03
  • 打赏
  • 举报
回复
to : lsftest() 呵呵, 都对都对哈
主要是楼住问题不明确, 你那红外控制搞的怎么样了?
今天升星了,高兴的啊。
pigsanddogs 2004-04-03
  • 打赏
  • 举报
回复
我是呆了2年多。。
go_my_sky 2004-04-02
  • 打赏
  • 举报
回复
利用系统函数获得随机数 a

再利用系统函数获得随机数 b

通过加减修改 b 值以达到整除。

这样算法复杂度很小。也达到随机的目的。
Rozre 2004-04-02
  • 打赏
  • 举报
回复
for ……next
NotReady 2004-04-02
  • 打赏
  • 举报
回复
Dim i As Long
Dim j As Long
Dim Flag As Boolean

Randomize
i = CLng(Rnd * 10000)

'MsgBox i

Randomize

Flag = False

For j = 2 To CLng(Sqr(i))
If i Mod j = 0 Then
Flag = True
Exit For
End If
Next

If Flag = False Then
MsgBox i & "不能被任何数整除!", vbInformation + vbOKOnly, "系统提示"
Else
MsgBox i & "能被" & j & "整除!", vbInformation + vbOKOnly, "系统提示"
End If
lsftest 2004-04-02
  • 打赏
  • 举报
回复
算法二: 是这样的,虽然temp=5000和temp=10和temp=1的机会是一样的多, 但
b(100000\temp) 为5000,10,1的机会却不是一样的多, rnd()*(100000\temp+1)
也不是, 因为整除号已经做了近似处理。 而楼主希望a,b都是“真正的”随机,
而不是中间值temp
==========================================================
是会有这样的情况,但这种情况并不是由于算法或计算失误所造成的(取整可能会有一点点影响),而是由题目本身的要求所造成的,b的取值受a的约束,a必然小于100000,而b是a的因数,即必须与另一数(temp)相乘才等于a。temp最小的取值为2,由上面可知:
a<=100000
a=b*temp
temp>=2
可得出b<=50000,所以不能要求b在1~100000以内随机。

可以把代码运行一遍, 我觉得结果最有说明力
==========================
虽然都是用第二种方法的思路,但我的步骤与你的有些不同,因为楼主只要求两个随机数,所以temp的值其实并不重要,我的方法是先保证数b的随机性,但如上所说,如果保证了b的随机性,就必然会影响a的随机性,由下面代码的测试结果证明了这一点,a大于50000与a小于50000的比例大概是8:2(我上面的代码里b的取值范围也错了,应该在1~50000之间而不是1~100000之间):
Private Sub Command1_Click()
Randomize
Dim a, b, step As Long
Dim upa, lowa As Long
For i = 1 To 100000
b = Int(50000 * Rnd + 1)
step = Int(100000 / b)
'从2到step取随机数temp
TEMP = Int((step - 1) * Rnd + 2)
a = b * TEMP
'Print Str(a) + "/" + Str(b) + "=" + Str(TEMP)
If a > 50000 Then
upa = upa + 1
Else
lowa = lowa + 1
End If
Next
Print upa, lowa, upb, lowb
End Sub
至于认为方法一不理想,是因为觉得这种方法把有些可能性忽略了,两害相权取其轻。。
要真正的随机,或许真的要回到老路(穷举a/2个数)上????
happywqw 2004-04-02
  • 打赏
  • 举报
回复
典型算法为:

1. 范围:{1,2,3,...,Max}=E;
2. 输入:A in E;
3. 范围:{1,...(A Mod 2)}=F;
4. 搜索所有B in F,使得A Mod B =0,得到B的集合{B};
5. 然后在集合{B}中随机取B(i)作为输出,{B}为空,则输出空。

如果是考虑算法效率问题,关键在第四步;如果想从搜索一开始便随机取值,以期获得随机性且满足条件的话,除非A、B存在必然数值关系,否则这种想法是不切实际的。

跟楼主思路一样!~:) 只是可以在加快搜索速度上可以改进!
pigsanddogs 2004-04-01
  • 打赏
  • 举报
回复
不同意,temp如果是真的随机数,从概率来说,它就应该在1~100000(重复一次,楼主要的值是100000以下)里面任意取值,各个数的机会均等,不能说temp=5000的机会就比temp=10的机会多。。我觉得这样算平均不合理。
=======================================================================
算法二: 是这样的,虽然temp=5000和temp=10和temp=1的机会是一样的多, 但
b(100000\temp) 为5000,10,1的机会却不是一样的多, rnd()*(100000\temp+1)
也不是, 因为整除号已经做了近似处理。 而楼主希望a,b都是“真正的”随机,
而不是中间值temp
做个假设:
假设随机了100000次,并且很公平的从1-100000都有值, 那么b为1的概率为50%。
因为大于50000的数被100000整除都为1, 而实际中( rnd()*(100000\temp+1 )为1的
概率还要大于50%,因为实际的值是在上面的(1~~b)中取出来的。所以我觉得
这个方法不是“真正的随机数字”
可以把代码运行一遍, 我觉得结果最有说明力
另:抱歉,我没仔细看题目,把100000看成了10000,所以里面所有的10000都要替换成100000
并且在方法一中,需要用cdbl转换,100000*100000会溢出,,
pigsanddogs 2004-03-31
  • 打赏
  • 举报
回复
方法一 从效率上来说, 是方法二的10000倍,因为数范围为1~10000*10000
从随机分布上来说, 明显好于方法二. 对于你的要求可以用一来实现
具体可以执行观看结果.
===========================
我想你可能理解错了986753421(做点什么?) 的意思,他的意思应该是这样的:先求数B,再求数A:
==================================================
我想你可能理解错了 pigsanddogs(我爱吃猪肉,但是长不胖,为什么??) 的意思, :)
lsftest 2004-03-31
  • 打赏
  • 举报
回复
方法一 从效率上来说, 是方法二的10000倍,因为数范围为1~10000*10000
从随机分布上来说, 明显好于方法二. 对于你的要求可以用一来实现
具体可以执行观看结果.
===========================
我想你可能理解错了986753421(做点什么?) 的意思,他的意思应该是这样的:先求数B,再求数A:
Private Sub Command1_Click()
Randomize
Dim a, b, step As Long
b = Int(100000 * Rnd + 1)
step = Int(100000 / b)
'从2到step取随机数temp
TEMP = Int((step - 1) * Rnd + 2)
a = b * TEMP
Print Str(a) + "/" + Str(b) + "=" + Str(TEMP)
End Sub
根本不必用循环,是好方法。。。只是不知合不合楼主的要求。
flyingscv 2004-03-31
  • 打赏
  • 举报
回复
除以一个随机数然后取整
EverythingIdo 2004-03-31
  • 打赏
  • 举报
回复
据我理解,这不是简单的算法!
1.首先随机取得一个a,然后使用“某种算法”随机取得一个b,使得mod(a/b)=0
2.关键,这里随机取一个b,至少需要使用一次Rnd()函数吧,由于使用了Rnd()这个函数,使得b具有不可预测性。
3.按照楼主的思路看,这个b不是一个真正的随机数,只是一个预赋值好的数组中随机成员!
4.这样,如果,单纯使用穷举遍历所有小于a的所有的整数,又不能满足“随机获得”b的要求,使用while...wend语句,那就有可能“死机”
cnTOMcn 2004-03-31
  • 打赏
  • 举报
回复
不知楼主是纯粹讨论算法还是有实际应用?

如是实际应用,有个比较另类的方法:
先选择一个比较小的B,再顺手乘个因子,得到A。
OK,交差。
“报告老师,我做好了!”:)
lsftest 2004-03-31
  • 打赏
  • 举报
回复
方法二虽然每次都能运算出, 但也不能算是"真正"的随机, 诚然, 他也可能获取
满足条件的任意组合, 但b,tmp都获中间(即都小于100)的概率是很小.
因为tmp从概率上说, 算平均的话, 应该是5000, 那么b的范围一般都是在1,2之间
这样也就是说, 最后运算出来的b,一般都是1,2很小的数字,概率上不算随机
=======================================================================
不同意,temp如果是真的随机数,从概率来说,它就应该在1~100000(重复一次,楼主要的值是100000以下)里面任意取值,各个数的机会均等,不能说temp=5000的机会就比temp=10的机会多。。我觉得这样算平均不合理。
pigsanddogs 2004-03-31
  • 打赏
  • 举报
回复
接上面. 回车不好使;
能满足条件, 但如上,不能产生真正的随机数字
所以为了让tmp,b都是"真正"的随机数, 所以在方法一中,我让他们都在10000取值
但这样,可能他们的值会比10000大,也可能比10000小. 所以,如果比10000大的,这次取
值就忽略掉; 所以有个概率问题, 就是说要大概1000多次才能取到一个这样的值.
但对于楼主来说,从随机分布来说, 从现在计算机的处理速度来说,这算不上什么.
所以我推荐用这个方法. 请你把代码运行看看. 然后让cnt/1000大概就知道平均算出
一个这样的值需要取多少次值.
方法二虽然每次都能运算出, 但也不能算是"真正"的随机, 诚然, 他也可能获取
满足条件的任意组合, 但b,tmp都获中间(即都小于100)的概率是很小.
因为tmp从概率上说, 算平均的话, 应该是5000, 那么b的范围一般都是在1,2之间
这样也就是说, 最后运算出来的b,一般都是1,2很小的数字,概率上不算随机

另;方法一; max(tmp) * max(b) = 10000 * 10000 是10000的10000倍
但任意rnd a * rnd b < 10000的概率却不是成正比关系, 可以用下面代码算出
dim i as long , j as long ,cnt
for i = 1 to 10000
for j = 1 to 10000
if i * j < 10000 then cnt = cnt + 1
next j
next i
debug.print 10000& * 10000 / cnt

大概 1067.88547996113 次就能取到一个那样的值
pigsanddogs 2004-03-31
  • 打赏
  • 举报
回复
max(temp)×max(b)=10000×10000=100000000>>100000,但我估计这可能是兄台的笔误吧。
但如果把程序改成:
tmp = Int(Rnd * 100 + 1)
b = Int(Rnd * 1000 + 1)
max(temp)×max(b)=100×1000=100000是可以,但却不能产生真正的随机,用上面这样的取数方式,有些数会被忽略了,例如,就产生不了88888(a)=44444×2这样的数,因为无论temp还是b都不会等于44444。
==============================>
确实如此. 如果让tmp,b都在100这个范围取值. 能满足a=b*tmp的条件,但
lsftest 2004-03-31
  • 打赏
  • 举报
回复
22可以被88888整除?
=======================
估计楼主想说的是222。
qyii 2004-03-31
  • 打赏
  • 举报
回复
88888 \ 22 = 4040.3636363636363636363636363636

TO:victorycyz(中海)
应该是举个例子吧~!没别的意思的.呵呵
pigsanddogs 2004-03-31
  • 打赏
  • 举报
回复
上面的, 效率约为方法二的1050次. 可以用cnt/1000观看.
加载更多回复(19)

7,759

社区成员

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

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