|
'第1参数 h: 指定目标总和?或 目标平均值?
'如需固定结果,则应复制后粘贴为数值。
'第2参数 h1 :返回结果的下限。直接指定,或平均值的0.x倍、1-x%倍等。
'第3参数 h2 :返回结果的上限。直接指定,或平均值的x倍、1+x%倍等。
'第4参数 n: 返回结果的个数?理论上整数范围即可无限制?实际数量几万以上可否没试过?
'第5参数 d :返回结果的小数位数。用法同Round(Num,d)即=0为整数、>0为小数位数、<0为向上取整。
'可选参数:
'第6参数 k :返回结果的模式。默认k=0 可选值4个: -1、0、1、2
'k=-1 时、返回不允许重复值的合并字符串结果。即只在1个单元格中返回结果。
'k= 0 时、返回 允许重复值的合并字符串结果。即只在1个单元格中返回结果。
'k= 1 时、返回不允许重复值的区域数组。即需要选中横向n列后输入三键数组公式。(Ctrl+Shift+Return)
'k= 2 时、返回 允许重复值的区域数组。即需要选中横向n列后输入三键数组公式。(Ctrl+Shift+Return)
'第7参数 l :返回结果是否包含h1、h2边界的模式。默认l=1 可选值2个: 0、1
'l =1 时、返回结果 包含边界。即结果范围是[h1,h2]的开区间。>=h1 并 <=h2
'l =0 时、返回结果不包含边界。即结果范围是(h1,h2)的开区间。> h1 并 < h2
'第8参数 m :随机试算的次数。默认m=30 可选范围为:>0的正整数。
'如认为计算结果不够随机,可增大m值如 m=100、m=3000……但m值越大,计算耗时越多。m太大可能会死机。
'如认为计算结果已够随机,而需要提高运算速度,可减小m值如 m=10。
Function GetRndSum(h#, h1#, h2#, n&, d%, Optional k% = 0, Optional l% = 1, Optional m% = 30)
Application.Volatile
Dim i&, r1&, r2&, t&, v&, cnt&
If h < h2 Then h = h * n
h = h * 10 ^ d: h1 = h1 * 10 ^ d: h2 = h2 * 10 ^ d
v = Int(h / n): If v < h1 Or v > h2 Then GetRndSum = "Average Err !": Exit Function
Retry:
cnt = cnt + 1
ReDim a&(n - 1)
For i = 1 To n - 1
a(i) = v
Next
a(0) = h - v * (n - 1)
Randomize
For i = 1 To n * m
r1 = Int(Rnd * n): r2 = Int(Rnd * (n - 1) + r1 + 1) Mod n
If h1 + h2 < a(r1) + a(r2) Then t = h2 - a(r2) Else t = a(r1) - h1
t = Int(Rnd * (t + l)): a(r1) = a(r1) - t: a(r2) = a(r2) + t
'l=1 [h1,h2] / l=0 (h1,h2)
Next
If k Mod 2 Then '-1,1 Check Unique
If cnt > m Then GetRndSum = "Duplicate": Exit Function
ReDim c&(h1 To h2)
For i = 0 To n - 1
If c(a(i)) = 0 Then c(a(i)) = 1 Else GoTo Retry
Next
End If
ReDim b(n - 1) '-1/1: Unique only 0/2: duplicate OK
For i = 0 To n - 1
b(i) = a(i) * 10 ^ -d
Next
If k > 0 Then GetRndSum = b Else GetRndSum = h * 10 ^ -d & "=" & Join(b, "+")
End Function
老师那您这个随机拆分的 可以改造成十进制的不?有时候有7,8位小数的时候会溢出!! |
|