4

第一种方法是可以的。第二个不断重复相同的数字对。

这对我来说很模糊为什么......你能指出好的方向吗?

module Normal = 
   let rnd = new MersenneTwister()
   let sampleNormal = 
      fun () -> let rec randomNormal() = let u1, u2 = rnd.NextDouble(),rnd.NextDouble()
                                         let r, theta= sqrt (-2. * (log u1)), 2. * System.Math.PI * u2  
                                         seq { yield r * sin theta; yield r * cos theta ; printfn "next";yield! randomNormal() }
                randomNormal()

   let sampleNormalBAD = 
      fun () -> let rec randomNormal = let u1, u2 = rnd.NextDouble(),rnd.NextDouble()
                                       let r, theta= sqrt (-2. * (log u1)), 2. * System.Math.PI * u2  
                                       seq { yield r * sin theta; yield r * cos theta ; printfn "next";yield! randomNormal }
                randomNormal

Normal.sampleNormal() |> Seq.take(10) |>Seq.toArray
Normal.sampleNormalBAD() |> Seq.take(10) |>Seq.toArray
4

2 回答 2

4

在第一个示例randomNormal()中是一个函数,它接受()并返回一个值,每次都会对其进行评估。在第二个randomNormal是一个值,所以它不会被评估两次,一旦有界它将保持相同的值。

如果您翻转randomNormal()签名是:

unit->seq<float>

而 forrandomNormal只是:

seq<float>

更新:它继续打印,因为它printfn在序列内,这是有界值。如果您尝试在最后一行之前的正文中打印,您会看到不同之处。这是一个简化的示例代码:

let sampleNormal = 
    fun () -> 
        let rec randomNormal() = 
            let u1, u2 = 1,2
            printfn "Evaluating"
            seq { yield u1; yield u2 ; printfn "next";yield! randomNormal() }
        randomNormal()

let sampleNormalBAD = 
    fun () -> 
        let rec randomNormal = 
            let u1, u2 = 1,2 
            printfn "Evaluating"
            seq { yield u1; yield u2 ; printfn "next";yield! randomNormal }
        randomNormal
于 2012-07-01T20:32:16.290 回答
0

完成 Gustavo 的答案,randomNormal是一个值,在被解释器计算后,绑定到一个序列。

进一步调用randomNormal将产生这个序列,并且在序列之前使用的绑定没有理由被评估。t、theta 等.. 将始终具有相同的值。序列的内容将被评估,因此打印。

randomNormal()同样的情况下,但会评估绑定,因为函数可能依赖于副作用。

于 2012-10-13T10:08:36.190 回答