【问题标题】:Choose a, c, m in Linear Congruential Generator在线性同余生成器中选择 a、c、m
【发布时间】:2016-07-03 16:46:20
【问题描述】:

我希望在 Excel 中实现一个线性同余生成器。

我们知道,我们必须选择LCG的参数是a、c、m和Z0。

Wikipedia 这么说

一般 LCG 的周期最多为 m,对于某些选择 因子 a 远低于此。 LCG将为所有人提供一个完整的时期 种子值当且仅当:

m and the offset c are relatively prime,
a - 1 is divisible by all prime factors of m,
a - 1 is divisible by 4 if m is divisible by 4.

还有,

 m, 0 < m  – the "modulus"
 a, 0 < a < m – the "multiplier"
 c, 0 < c < m – the "increment"
 Z0, 0 < Z0 < m – the "seed" or "start value"

我需要选择那些值,我希望 Z0 的初始值为 10113383,其余的都是随机的。不,哪些值具有指定的时间段并保证在该时间段内不会发生冲突?

我尝试输入一些值,a=13, c=911, m=11584577,看起来没有冲突。但我不确定我是否违反了规则。

【问题讨论】:

  • 因此请进行数学运算以确定您的数字是否符合标准。
  • @JimMischel 你的意思是像 m 这样的数学和偏移量 c 是互质的吗?
  • 是的,我就是这个意思。

标签: excel math random lcg vba


【解决方案1】:

我定期教授数论和密码学课程,因此建立了 VBA 和 Python 程序库。使用这些,我只需要再写一个:

Function GCD(num1 As Long, num2 As Long) As Long
    Dim a As Long
    Dim b As Long
    a = num1
    b = num2
    Dim R As Long
    R = 1
    Do Until R = 0
        R = a Mod b
        a = b
        b = R
    Loop
    GCD = a
End Function

Sub Helper_Factor(ByVal n As Long, ByVal p As Long, factors As Collection)
    'Takes a passed collection and adds to it an array of the form
    '(q,k) where q >= p is the smallest prime divisor of n
    'p is assumed to be odd
    'The function is called in such a way that
    'the first divisor found is automatically prime

    Dim q As Long, k As Long

    q = p
    Do While q <= Sqr(n)
        If n Mod q = 0 Then
            k = 1
            Do While n Mod q ^ k = 0
                k = k + 1
            Loop
            k = k - 1 'went 1 step too far
            factors.Add Array(q, k)
            Helper_Factor n / q ^ k, q + 2, factors
            Exit Sub
        End If
        q = q + 2
    Loop
    'if we get here then n is prime - add it as a factor
    factors.Add Array(n, 1)
End Sub

Function Factor(ByVal n As Long) As Collection
    Dim factors As New Collection
    Dim k As Long

    Do While n Mod 2 ^ k = 0
        k = k + 1
    Loop
    k = k - 1
    If k > 0 Then
        n = n / 2 ^ k
        factors.Add Array(2, k)
    End If
    If n > 1 Then Helper_Factor n, 3, factors
    Set Factor = factors
End Function

Function DisplayFactors(n As Long) As String
    Dim factors As Collection
    Dim i As Long, p As Long, k As Long
    Dim sfactors As Variant

    Set factors = Factor(n)
    ReDim sfactors(1 To factors.Count)
    For i = 1 To factors.Count
        p = factors(i)(0)
        k = factors(i)(1)
        sfactors(i) = p & IIf(k > 1, "^" & k, "")
    Next i
    DisplayFactors = Join(sfactors, "*")
End Function

Function MaxPeriod(a As Long, c As Long, m As Long) As Boolean
    'assumes 0 < a,c < m
    Dim factors As Collection
    Dim p As Long, i As Long

    If GCD(c, m) > 1 Then Exit Function 'with default value of False
    If m Mod 4 = 0 And (a - 1) Mod 4 > 0 Then Exit Function
    'else:
    Set factors = Factor(m)
    For i = 1 To factors.Count
        p = factors(i)(0)
        If p < m And (a - 1) Mod p > 0 Then Exit Function
    Next i
    'if you survive to here:
    MaxPeriod = True
End Function

例如,在中间窗口中您可以检查:

?maxperiod(13,911,11584577)
True

看来你运气不错

【讨论】:

  • 我可以使用哪个 IDE 来测试该代码?我想尝试其他值
  • 这是 Excel VBA。您的问题是关于 Excel 的,所以我认为这很明显,尽管我只是注意到没有 vba 标签(我可能会添加该标签,以便其他人可以加入)。只需打开 VBA 编辑器,插入标准代码模块,然后复制此代码。如果你没有学过 VBA,有很多教程、youtube 视频等。请注意,函数MaxPeriod 可以直接在电子表格本身上使用。有你的参数,例如A1:A3 然后在 A4 中放置公式=MaxPeriod(A1,A2,A3)
猜你喜欢
  • 2012-08-19
  • 1970-01-01
  • 2015-08-22
  • 2013-10-09
  • 1970-01-01
  • 2019-11-20
  • 1970-01-01
  • 1970-01-01
  • 2013-07-11
相关资源
最近更新 更多