版权声明:可以任意转载,转载时请务必以超链接形式标明如下文章原始出处和作者信息及本声明
作者:xixi
出处:http://blog.csdn.net/slowgrace/archive/2009/03/25/4022632.aspx
1、生成随机数的方法
Function
SetEmpId()
As
String
Dim
ref
As
String
Randomize
ref
=
Int((
99999
-
10000)
*
Rnd
+
10000)
SetEmpId
=
ref
End
Function
This function’s purpose is to assign a unique five-digit number to each new employee. To generate a random integer between two given integers where ending_number = 99999 and beginning_number = 10000, the following formula is used:
= Int((ending_number - beginning_number) * Rnd + beginning_number)
2、按概率生成随机整数
以下参考:http://topic.csdn.net/t/20051018/10/4333135.html
如果要随机生成5个数,并控制它们出现的概率.
数字 概率
1 10%
2 10%
3 10%
4 20%
5 50%
那就生成0-1的随机数
0 -- 0.1 1
0.1 -- 0.2 2
0.2 -- 0.3 3
0.3 -- 0.5 4
0.5 -- 1.0 5
3、按概率生成随机浮点数
以下来自和Tiger_Zhao的讨论。
如果要控制1个数落在某个区间的概率,比如要求在sngBegin和sngEnd之间生成一个随机数,这个随机数落在sngPB和sngPE之间的概率是P%。有两种方法,以第二种方法为好。
先说第一种方法,要点是:
(1)由于sngPB和sngPE将整个区间分成3部分,所以先分别计算随机数落在3部分的概率。落在sngPB和sngPE之间的概率是P%,这是已知的。余下的两个区间的总和概率是(1-p%),分到各个区间的概率按它们的长度分成。
(2)然后根据3个概率得到一个区间划分,落在第一个区间的,就在sngPB和sngPE之间生成一个随机数;落在第二个区间的,就是[sngBegin, sngPB]里生成随机数;落在第3个区间的,就在[sngPE,sngEnd]之间生数。
'create a random number between sngBegin and sngEnd
'with a probability of bytP to lie within sngPB and sngPE
Public
Function
GetRndNumP(
sngBegin
As
Single
,
sngEnd
As
Single
,
sngPB
As
Single
,
sngPE
As
Single
,
bytP
As
Byte)
As
Single
Dim
bytP1
As
Byte
,
bytP2
As
Byte
Debug
.
Assert (
sngPB
>=
sngBegin)
And (
sngPE
>=
sngPB)
And (
sngEnd
>=
sngPE)
'计算其他区间的概率
bytP1
= ((
sngPB
-
sngBegin)
/ ((
sngEnd
-
sngBegin)
- (
sngPE
-
sngPB)))
* (
100
-
bytP)
'[sngBegin, sngPB]
bytP2
=
100
-
bytP
-
bytP1
'[sngPE, sngEnd]
'依据概率投射到相应区间
Select
Case
GetRandomNum(
1
,
100)
Case
1
To
bytP
GetRndNumP
=
GetRandomNum(
sngPB
,
sngPE)
Case (
bytP
+
1)
To (
bytP
+
bytP1)
GetRndNumP
=
GetRandomNum(
sngBegin
,
sngPB)
Case (
bytP
+
bytP1)
+
1
To
100
GetRndNumP
=
GetRandomNum(
sngPE
,
sngEnd)
End
Select
End
Function
Public
Function
GetRandomNum(
sngBegin
As
Single
,
sngEnd
As
Single)
As
Single
Randomize
GetRandomNum
= (
sngEnd
-
sngBegin)
*
Rnd
+
sngBegin
End
Function
这个办法有个问题,就是用了两次随机数,这样实际上影响了它的随机性。Tiger_Zhao建议的第二种方法则没有这个问题,做法是:多个段有不同权重时其实可以映射成相同权重(缩放 [sngPB, sngPE] 区间,相对调整 sngEnd),这样只要一次 Rnd() 就可以完成,代码如下。
'create a random number between sngBegin and sngEnd
'with a probability of bytP to lie within sngPB and sngPE
Public
Function
GetRndNumP(
sngBegin
As
Single
,
sngEnd
As
Single
,
sngPB
As
Single
,
sngPE
As
Single
,
bytP
As
Byte)
As
Single
Dim
sngPLen
As
Single
Dim
sngTLen
As
Single
'total length
Dim
sngIncreased
As
Single
'需要缩放的长度
Dim
sngResult
As
Single
sngPLen
=
sngPE
-
sngPB
sngTLen
=
sngEnd
-
sngBegin
Debug
.
Assert (
sngPB
>=
sngBegin)
And (
sngPE
>=
sngPB)
And (
sngEnd
>=
sngPE)
Debug
.
Assert (
bytP
<
100)
And (
bytP
>
0)
Debug
.
Assert
sngTLen
<>
sngPLen
'映射原来的区间为等权重区间
If (
sngPLen
/
sngTLen)
*
100
=
bytP
Then
GetRndNumP
=
GetRandomNum(
sngBegin
,
sngEnd)
Exit
Function
End
If
'((sngPLen + sngIncreased) / (sngTLen + sngIncreased)) * 100 = bytP
sngIncreased
= ((
bytP
/
100)
*
sngTLen
-
sngPLen)
/ (
1
- (
bytP
/
100))
'缩放回原来区间
sngResult
=
GetRandomNum(
sngBegin
,
sngEnd
+
sngIncreased)
Select
Case
sngResult
Case
sngBegin
To
sngPB
GetRndNumP
=
sngResult
Case
sngPB
To (
sngPE
+
sngIncreased)
'等比例缩放
GetRndNumP
=
sngPB
+ (
sngResult
-
sngPB)
*
sngPLen
/ (
sngPLen
+
sngIncreased)
Case (
sngPE
+
sngIncreased)
To
sngEnd
+
sngIncreased
'简单平移
GetRndNumP
=
sngResult
-
sngIncreased
End
Select
End
Function
另,yesvery说,VB产生的是伪随机数,不是真正的随机数。所以,不能完全满足正态分布。