如何在 Rust 中生成一定范围内的随机数?

问题描述 投票:0回答:5

编者注:此代码示例来自 Rust 1.0 之前的版本,在语法上不是有效的 Rust 1.0 代码。此代码的更新版本会产生不同的错误,但答案仍然包含有价值的信息。

我遇到了以下如何使用 Rust 生成随机数的示例,但它似乎不起作用。该示例没有显示它适用于哪个版本的 Rust,所以也许它已经过时了,或者也许我弄错了。

// http://static.rust-lang.org/doc/master/std/rand/trait.Rng.html

use std::rand;
use std::rand::Rng;

fn main() {
    let mut rng = rand::task_rng();
    let n: uint = rng.gen_range(0u, 10);
    println!("{}", n);
    let m: float = rng.gen_range(-40.0, 1.3e5);
    println!("{}", m);
}

当我尝试编译它时,出现以下错误:

test_rand002.rs:6:17: 6:39 error: type `@mut std::rand::IsaacRng` does not
implement any method in scope named `gen_range`
test_rand002.rs:6    let n: uint = rng.gen_range(0u, 10);
                                   ^~~~~~~~~~~~~~~~~~~~~~
test_rand002.rs:8:18: 8:46 error: type `@mut std::rand::IsaacRng` does not
implement any method in scope named `gen_range`
test_rand002.rs:8    let m: float = rng.gen_range(-40.0, 1.3e5);
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

同一页面(上面)上还有另一个示例(如下),可以正常工作。然而,尽管我可以调整它,但它并没有完全达到我想要的效果。

use std::rand;
use std::rand::Rng;

fn main() {
    let mut rng = rand::task_rng();
    let x: uint = rng.gen();
    println!("{}", x);
    println!("{:?}", rng.gen::<(f64, bool)>());
}

如何使用 Rust(例如:

i64
)在给定范围(例如:0 到 n)内生成“简单”随机数?

random rust rust-obsolete
5个回答
129
投票

这会使用

Rng::gen_range
:

生成 0(含)和 100(不含)之间的随机数
use rand::Rng; // 0.8.5

fn main() {
    // Generate random number in the range [0, 99]
    let num = rand::thread_rng().gen_range(0..100);
    println!("{}", num);
}

不要忘记将

rand
依赖项添加到 Cargo.toml:

[dependencies]
rand = "0.8"

28
投票

编者注:此答案适用于 Rust 1.0 之前的版本,在 Rust 1.0 中无效。请参阅 Manoel Stilpen 的答案

最近这个变化很大(抱歉!都是我造成的),在 Rust 0.8 中它被称为

gen_integer_range
(注意 URL 中的
/0.8/
而不是
/master/
,如果你使用的是 0.8, 需要阅读这些文档)。

警告一句:

.gen_integer_range
在很多方面都是完全错误的,新的
.gen_range
没有不正确的问题。


master代码(其中

.gen_range
工作正常):

use std::rand::{task_rng, Rng};

fn main() {
    // a number from [-40.0, 13000.0)
    let num: f64 = task_rng().gen_range(-40.0, 1.3e4);
    println!("{}", num);
}

17
投票

Rng::gen_range
的文档指出:

此函数针对给定范围内仅生成单个样本的情况进行了优化。另请参阅

Uniform
分布类型,如果重复从同一范围采样,可能会更快。

Uniform
可用于生成单个值:

use rand::distributions::{Distribution, Uniform}; // 0.6.5

fn main() {
    let step = Uniform::new(0, 50);
    let mut rng = rand::thread_rng();
    let choice = step.sample(&mut rng);
    println!("{}", choice);
}

游乐场

或者生成值的迭代器:

use rand::distributions::{Distribution, Uniform}; // 0.6.5

fn main() {
    let step = Uniform::new(0, 50);
    let mut rng = rand::thread_rng();
    let choices: Vec<_> = step.sample_iter(&mut rng).take(10).collect();
    println!("{:?}", choices);
}

游乐场


0
投票

自 2024 年以来,nightly Rust 已经有了

random
API,它允许您轻松生成随机数,无需外部 crate。以下是
u64
的示例实现:

#![feature(random)] // requires nightly toolchain

fn random_u64_in_range(range: impl std::ops::RangeBounds<u64>) -> u64 {
    use std::ops::Bound::*;

    let min = match range.start_bound() {
        Included(&num) => num,
        Excluded(&num) => num + 1,
        Unbounded => 0
    };

    let max = match range.end_bound() {
        Included(&num) => num,
        Excluded(&num) => num - 1,
        Unbounded => u64::MAX
    };

    if min >= max {
        return min; // alternatively, panic
    }

    let output_mask = u64::MAX >> (max - min).leading_zeros();

    // Repeatedly generate random numbers until one is found within the range.
    // A simpler method would be to return random() % (max - min) + min,
    // but this could result in a slight bias in the generated values.
    std::iter::repeat_with(|| std::random::random::<u64>() & output_mask)
        .find(|&trial| trial <= max - min).unwrap() + min
}

fn main() {
    let val = random_u64_in_range(..=10); // from 0 to 10, inclusive
    println!("{}", val);
}

请注意,正确执行此操作有点棘手,因为

random() % (max - min) + min
的明显方法会导致有偏差的结果。这可以很容易地看出,(例如)如果你想生成一个从 1 到 3 的数字,你有三种可能的结果,但是没有办法将 2^64 个可能的
random()
值划分为三个相等的值团体。


-4
投票

为什么不直接使用模数呢?

let x = rng.gen<u32>() % 25

因此您的值将在 0 到 24 之间。如果您需要不同的范围,请添加偏移量。

© www.soinside.com 2019 - 2024. All rights reserved.