ZetCode

F# 随机

最后修改时间 2025 年 5 月 1 日

在本文中,我们将展示如何在 F# 中生成随机值。在 .NET 中,内置的 Random 类用于生成随机值。

Random 代表一个伪随机数生成器,它是一种生成满足随机性某些要求的数字序列的算法。

随机数生成器

随机数生成器 (RNG) 产生一组在外观上不显示任何可区分模式的值。

我们有两种随机数生成器:硬件随机数生成器和伪随机数生成器。硬件随机数生成器被认为能产生真正的随机数。伪随机数生成器基于软件算法生成值;它们生成看起来随机的值。但是,如果算法已知,这些值是确定的,并且可以被复制。

随机生成器用于密码学、赌博、游戏和模拟。

注意: 为获得最佳安全性,必须使用密码学安全的伪随机数生成器。

为了改进伪随机数生成器,操作系统会使用从设备驱动程序、用户输入延迟或一个或多个硬件组件的抖动收集的环境噪声。这是密码学安全的伪随机数生成器的核心。

种子

种子是初始化随机数生成器的值。随机数生成器通过对先前生成的值执行某些操作来生成值。当算法启动时,种子是生成器操作的初始值。生成器的关键部分是提供一个接近真正随机数的种子。

let rnd = Random()

构造函数创建一个带有默认种子的随机数生成器。

注意: 自 2016 年以来,在 .NET Core 中,默认种子已从 Environment.TickCount 更改为 Guid.NewGuid().GetHashCode()。在循环中创建多个随机实例是安全的。

F# 随机 Next

Next 函数返回一个随机整数。我们可以为随机数指定下限和上限。

main.fsx
open System

let rnd = new Random()

for _ in 1..20 do
    let r = rnd.Next(1, 100)
    printf "%d " r

printfn ""

在程序中,我们生成 20 个随机整数。

open System

Random 类位于 System 命名空间中。

let r = rnd.Next(1, 100)

下界是包含的,上界是不包含的。

λ dotnet fsi main.fsx
29 41 92 36 10 4 41 18 17 62 9 60 58 69 11 4 44 12 31 98 

F# 随机选择元素

在下面的示例中,我们从列表中选择一个随机元素。

main.fsx
open System

let words = ["sky"; "cup"; "tall"; "falcon"; "cloud"]

let rnd = Random()
let re = words |> List.item (rnd.Next(words.Length))

printfn "%s" re

在程序中,我们从单词列表中选择一个随机字符串。

let re = words |> List.item (rnd.Next(words.Length))

我们将一个随机索引传递给 List.item 函数。Next 函数的上界是列表的大小。

λ dotnet fsi main.fsx
cloud

下一个示例选择几个随机值。

main.fsx
open System

let rnd = new Random()

let vals = [ 1..100 ]
let idx = [ for _ in 1..7 -> rnd.Next(0, 100) ]

let res = idx |> List.map (fun e -> (List.item e vals))
printfn "%A" res

我们从整数列表中随机选择七个值。

let vals = [ 1..100 ]

使用范围运算符,我们创建了一个从 1 到 100 的整数列表。

let idx = [ for _ in 1..7 -> rnd.Next(0, 100) ]

在第二步中,我们生成七个随机索引。

let res = idx |> List.map (fun e -> (List.item e vals))

使用 List.mapList.item,我们使用生成的随机索引从 vals 列表中选择七个值。

λ dotnet fsi main.fsx
[84; 11; 68; 29; 87; 34; 61]

F# 生成随机值列表

在下一个示例中,我们创建一个新的随机值列表。

main.fsx
open System

let rnd = Random()

let rndVals =
    [ for i in 0..100 do
          rnd.Next(1, 101) ]

printfn "%A" rndVals

创建了一个包含一百个从 1 到 100 的随机整数的列表。

let rndVals =
    [ for i in 0..100 do
          rnd.Next(1, 101) ]

该列表是使用 F# 列表推导式创建的。

λ dotnet fsi main.fsx
[79; 7; 33; 66; 85; 44; 31; 97; 3; 43; 93; 53; 45; 68; 83; 46; 59; 58; 17; 63;
 80; 94; 98; 11; 65; 82; 41; 49; 100; 58; 54; 88; 53; 88; 50; 8; 55; 11; 21; 42;
 20; 17; 41; 51; 98; 90; 32; 51; 60; 15; 65; 94; 78; 32; 49; 5; 28; 38; 39; 12;
 43; 45; 5; 34; 67; 34; 96; 53; 86; 83; 75; 81; 88; 55; 25; 87; 47; 74; 54; 11;
 93; 31; 97; 49; 32; 31; 29; 95; 87; 78; 44; 31; 33; 66; 38; 74; 50; 1; 9; 51;
 ...]

在下一个示例中,我们创建了一个随机选择列表。

main.fsx
open System

type Choice =
    | A
    | B
    | C

let getVal () =
    match Random().Next(1, 4) with
    | 1 -> A
    | 2 -> B
    | _ -> C

let chx = [ for _ in 1..7 -> getVal () ]
printfn "%A" chx

该程序生成一个随机选择的自定义类型列表。

type Choice =
| A
| B
| C

通过判别联合,我们定义了一个自定义的 Choice 类型。我们想要这些类型的随机列表。

let getVal () =
    match Random().Next(1, 4) with
    | 1 -> A
    | 2 -> B
    | _ -> C

我们定义了一个使用匹配表达式和 Next 函数来获取新的随机 Choice 值的函数。

let chx = [ for _ in 1..7 -> getVal () ]

getVal 函数在列表推导式中被调用,以构建一个新的随机选择列表。

λ dotnet fsi main.fsx
[B; C; C; C; C; C; A]

F# 随机无尽序列

下面的例子从一个无尽的随机序列中选择一些随机值。

main.fsx
open System

let rnd = Random()

let randomVals =
    seq {
        while true do
            yield rnd.Next(100)
    }

let firstTenRandom =
    randomVals
    |> Seq.truncate 10
    |> Seq.sort
    |> Seq.toList

printfn "%A" firstTenRandom

我们定义了一个从 1 到 100 的无尽随机整数序列。从这个序列中,我们选择十个值。

let randomVals =
    seq {
        while true do
            yield rnd.Next(100)
    }

while 循环用于创建无尽序列。yield 在每次循环中返回一个新项。

let firstTenRandom =
    randomVals
    |> Seq.truncate 10
    |> Seq.sort
    |> Seq.toList

使用 Seq.truncate,我们从序列中获取十个值。我们使用 Seq.sort 对值进行排序,并使用 Seq.toList 将其转换为列表。

λ dotnet fsi main.fsx
[15; 51; 52; 61; 77; 77; 78; 81; 87; 90]

在本文中,我们用 F# 语言生成了随机值。

作者

我叫 Jan Bodnar,我是一名充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。