f# - 如何使数组洗牌函数在后续调用中产生不同的结果

标签 f#

我有以下函数,可以按我想要的方式进行单次调用:

let shuffle (arr : 'a array) =
    let array = Array.copy arr
    let rng = new Random()
    let n = array.Length
    for x in 1..n do
        let i = n-x
        let j = rng.Next(i+1)
        let tmp = array.[i]
        array.[i] <- array.[j]
        array.[j] <- tmp
    array

但是,对于如下所示的多个调用(x 不用于任何用途),它会为每个调用产生相同的随机播放。如何让它每次产生不同的随机播放?

[for x in 1..3 do yield shuffle [|1;2;3|]]

>
val it : int [] list = [[|1; 3; 2|]; [|1; 3; 2|]; [|1; 3; 2|]]

最佳答案

您想将随机数移到函数之外,如下所示:

let rng = new Random()
let shuffle (arr : 'a array) =
    let array = Array.copy arr
    let n = array.Length
    for x in 1..n do
        let i = n-x
        let j = rng.Next(i+1)
        let tmp = array.[i]
        array.[i] <- array.[j]
        array.[j] <- tmp
    array

原因是 RNG 默认按时间播种,这在紧密循环中变化不够。将 rng 移到函数之外意味着它在调用过程中仍然存在。

关于f# - 如何使数组洗牌函数在后续调用中产生不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21070908/

相关文章:

types - F# 如何从其他模块推断类型和标签?

F# 在 SharpDevelop 上/在 SharpDevelop 中?

.net - F# 引用另一个文件中的模块函数

f# - 在类型成员中使用内联失败并出现 FS1114、FS1113、FS1116、FS1118

f# - 如何使记录实现接口(interface)?

.net - 为什么 F# inline 会导致 11 倍的性能提升

.net - System.Random().Next() 返回相同的结果

F# 和接口(interface)协方差 : what to do?(特别是 seq<> aka IEnumerable<>)

F# 有区别的联合类型问题

.net - 如何从 F# 中的数组列表中提取元素?