【问题标题】:Linear Congruential Generator on VBAVBA 上的线性同余生成器
【发布时间】: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 的范围内

标签: vba excel random


【解决方案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 的实现更健壮,那就太好了。
猜你喜欢
  • 1970-01-01
  • 2015-08-22
  • 2013-10-09
  • 1970-01-01
  • 2019-11-29
  • 2013-07-11
  • 1970-01-01
  • 2016-07-03
  • 2012-08-19
相关资源
最近更新 更多