看到一个单子,要求给定一个区间范围,随机生成一串数字,这些数字之和为指定值。后来花两个小时做出来了,这里记录一下。
思路:
首先生成指定范围内的数字,然后将所有数字之和相加,判断其与指定值之间的关系(找出其与指定数之间的差值)。
- 如果比指定值大,那么就将生成的随机数减小。从第一个随机数开始,先判断当前随机数减去差值后是否还在区间内部(与最小范围比较),如果还在,则直接将当前随机数改为减去差值之后的数字,跳出循环。如果不在,则在当前数和最小范围内重新生成一个随机数,然后用差值减去当前数和随机数之间的值,继续下次修正
- 如果比指定值小,那么将生成的随机数增大。从第一个数开始,判断当前随机数加上差值之后的数字是否还在区间内部(与最大范围比较),如果在,则直接将当前随机数改为加上差值之后的数字,跳出循环。如果不在,则在当前数和最大范围内重新生成一个随机数,然后用差值加上当前数和随机数之间的值,继续下次修正
在最坏的情况下,需要修正随机数个数的次数。如果在最后一次修正都无法成功,则给出一个提示,人工修正。(因为这里只对所有数修正了一次,所以需要人工修正,如果多次修正,理论上是可以成功的)
附一个vba的小代码
Function calculateData(ByRef tBorder, ByRef bBorder, ByVal frequency)
Dim total, temp As Double
Dim index, jump As Integer
'生成随机数
total = 0
For i = 0 To 16
randNum(i) = Round(Rnd() * (tBorder(i) - bBorder(i)) + bBorder(i), 3)
total = total + randNum(i)
Debug.Print (total)
Next
'写入表格
index = 0
For Each Item In Range("C5:S5")
Item.Value = randNum(index)
index = index + 1
Next
'修正
jump = 0
temp = 0
Do While total <> 0 And jump < 17
gapV = randNum(jump) - total
If total > 0 Then
If gapV > bBorder(jump) Then
randNum(jump) = gapV
total = 0
jump = 17
Else
temp = Round(Rnd() * (randNum(jump) - bBorder(jump)) + bBorder(jump), 3) '生成一个比当前数更小的数字
total = total - (randNum(jump) - temp)
randNum(jump) = temp
End If
Else
If gapV < tBorder(jump) Then
randNum(jump) = gapV
total = 0
jump = 17
Else
temp = Round(Rnd() * (tBorder(jump) - randNum(jump)) + randNum(jump), 3) '生成 一个比当前数更大的数字
total = total + (temp - randNum(jump))
randNum(jump) = temp
End If
End If
jump = jump + 1
Loop
If total <> 0 Then
randNum(16) = 1000
End If
'写入表格
index = 0
For Each Item In Range("C" & frequency & ":S" & frequency)
Item.Value = randNum(index)
index = index + 1
Next
End Function