F# 实例化PRNG的前几个值接近0

F# 实例化PRNG的前几个值接近0,f#,F#,朋友们,从下面的PRNG生成的第一个(可能是两个)值要么是0,要么接近它,不管种子是什么。有没有一种方法可以用构造函数或者更好的方法来初始化它,而不必烧掉几个值 type PRNGXXX(seed) = let mutable s : uint64[] = Array.zeroCreate 2 let rotl(x : uint64, k : int) = (x <<< k) ||| (x >>> (64 - k))

朋友们,从下面的PRNG生成的第一个(可能是两个)值要么是0,要么接近它,不管种子是什么。有没有一种方法可以用构造函数或者更好的方法来初始化它,而不必烧掉几个值

type PRNGXXX(seed) =
    let mutable s : uint64[] =  Array.zeroCreate 2

    let rotl(x : uint64, k : int) =
        (x <<< k) ||| (x >>> (64 - k))

    do s.[1] <- uint64 seed

    let sample() : uint64 =
        let s0 : uint64 = s.[0]
        let mutable s1 : uint64 = s.[1]
        let result : uint64 = s0 + s1

        s1 <- s1 ^^^ s0
        s.[0] <- rotl(s0, 24) ^^^ s1 ^^^ (s1 <<< 16)
        s.[1] <- rotl(s1, 37)

        result

    member x.NextDouble() = (float (sample())) / float System.UInt64.MaxValue
类型PRNGXXX(种子)=
让可变的s:uint64[]=Array.zeroCreate 2
let rotl(x:uint64,k:int)=
(x>(64-k))

do s.[1]答案在您发布的链接的评论中:“必须对状态进行种子设定,以使其并非处处为零。如果您有64位种子,我们建议对splitmix64生成器进行种子设定,并使用其输出填充s。”您所做的只是对128位状态的下半部分进行种子设定,因此上半部分为零。结果:对
next()
的第一次调用将精确返回您输入的种子(注意
Result
s0
s1
混合在一起之前是如何计算的:在第一次调用时,
s0
是0,
s1
是您的初始种子)

两种解决方案:一种是修改PRNG类以采用两个uint64值,如下所示:

type PRNGXXX(seed0, seed1) =
    let mutable s : uint64[] =  Array.zeroCreate 2
    // ...    
    do
        s.[0] <- uint64 seed0
        s.[1] <- uint64 seed1
    // ...

我建议使用两个64位的值作为种子,而不是通过splitmix运行的一个64位的值,因为在后一种情况下,真正的熵只有64位,而不是128位。

答案在您发布的链接的评论中:“国家必须被播种,这样它就不会到处都是零。如果您有64位种子,我们建议为splitmix64生成器设定种子,并使用其输出填充s。“您所做的只是设定128位状态的下半部分,因此上半部分为零。结果:对
next()
的第一次调用将准确返回您输入的种子(注意在将
s0
s1
混合在一起之前如何计算
result
:在第一次调用时,
s0
是0,
s1
是您的初始种子)

两种解决方案:一种是修改PRNG类以采用两个uint64值,如下所示:

type PRNGXXX(seed0, seed1) =
    let mutable s : uint64[] =  Array.zeroCreate 2
    // ...    
    do
        s.[0] <- uint64 seed0
        s.[1] <- uint64 seed1
    // ...

我建议使用两个64位值作为种子,而不是通过splitmix运行的一个64位值,因为在后一种情况下,真正的熵只有64位,而不是128位。

问题已解决。谢谢。msft是否开源实现System.Random()?谷歌搜索建议使用mersenne_twister_引擎,但似乎找不到实现..Net Framework实现:和.Net核心实现:问题已解决。谢谢。msft是否开放源代码实现System.Random()?谷歌搜索建议使用mersenne_twister_引擎,但似乎找不到实现..Net框架实现:和.Net核心实现:
uint64_t next() {
    uint64_t z = (x += UINT64_C(0x9E3779B97F4A7C15));
    z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
    z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
    return z ^ (z >> 31);
}