VBA 上的线性同余生成器
Posted
技术标签:
【中文标题】VBA 上的线性同余生成器【英文标题】:Linear Congruential Generator on VBA 【发布时间】:2018-03-22 15:05:40 【问题描述】:我正在尝试在 VBA 中复制线性同余生成器,但我的程序返回错误“6”:溢出...
Sub test()
Dim a As Long, c As Long, period As Long
Dim seed As Long, sample As Long, max As Long
Dim i As Long
seed = 1234
sample = 2
max = 100
a = 48271
c = 0
period = 2 ^ 31 - 1
For i = 1 To sample
seed = (a * seed + c) Mod period
Next i
End Sub
我认为问题在于for循环的第一个表达式,详细
a*seed
在循环的第二步。 任何解决问题而不分裂的建议
a*seed
在
(100*seed+100*seed+100*seed+...+(a-100*n)*seed
【问题讨论】:
@CallumDA 我尝试将每个数字声明为 Long 但它仍然会溢出 调试函数说seed = (a*seed+c) Mod period 我已经更新了你的问题,所以代码是最小的并且可以立即重复——因为我已经更新了声明并且问题仍然存在我现在也删除了我的答案 好的,非常感谢! @MathieuGuindon,是的。我将seed =
换成了Debug.Print
,它工作得很好——输出是59566414
。在Long
的范围内
【参考方案1】:
您可以使用变体的decimal subtype 并为小数编写自己的 mod 函数:
Function DecMod(a As Variant, n As Variant) As Variant
Dim q As Variant
q = Int(CDec(a) / CDec(n))
DecMod = a - n * q
End Function
Sub test()
Dim a As Variant, c As Variant, period As Variant
Dim seed As Variant, sample As Long, max As Long
Dim i As Long
seed = CDec(1234)
sample = 5
max = 100
a = CDec(48271)
c = 0
period = CDec(2 ^ 31 - 1)
For i = 1 To sample
Debug.Print seed
seed = DecMod(seed * a + c, period)
Next i
End Sub
输出:
1234
59566414
1997250508
148423250
533254358
【讨论】:
不错的解决方法 (+1)...不要以为您知道原始溢出的原因吗?我真的希望得到一个解释! @CallumDA 在原始代码中(使用Long
),当VBA 尝试将1234*59566414
评估为Long 时,溢出发生在第二次循环中。如果其中一个操作数溢出,那么即使结果 Mod
没有溢出,整个计算也会溢出。如果Mod
的实现更健壮,那就太好了。以上是关于VBA 上的线性同余生成器的主要内容,如果未能解决你的问题,请参考以下文章