在偏向中间的范围内生成随机无符号整数

Generating random unsigned integers within a range biased toward the middle

我试图在一个非常窄的范围内生成多个随机 u32 整数。我的最大值和最小值都在 1 到 6 之间变化。我想将生成器偏向范围的中间。

我有 tried using the Normal distribution from the rand_distr crate,但它似乎是针对浮点数和无限概率的,即我想要 2 到 5 之间的值,但我可能会得到像 0.81 或 6.92 这样的结果,即使它们相当罕见.我无法在文档中找到 Normal 发行版的整数版本。我假设它不存在。

我也希望它是高效的,所以我感觉浮点数的正态分布不会非常高效。我还注意到一个称为加权索引的分布,但这需要在每次迭代时手动计算权重。

也许在生成器运行后,整数值的常规 get_range 可以以某种方式在算术上偏向平均值。有人对此有任何有趣的解决方案吗?

一个粗略的解决方案:从区间内的均匀分布中取 2 个数字并使用平均值。

它会给出这样的分布:_/\_

为了更精细的控制,您需要一些逐步插值。

如果您希望从值样本中获得有偏差的随机分布,您可以使用 rand crate's rand::distributions::weighted::WeightedIndex 通过定义样本中每个项目的权重来精细控制偏差。

use rand::prelude::*;
use rand::distributions::WeightedIndex;

fn main(){

    let mut rng = thread_rng();
    //item value and it's weight increasing till middle and then decreasing till end
    let sample_item = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 3), ('f', 2), ('g', 1)];


    let weight_dist = WeightedIndex::new(sample_item.iter().map(|(_, weight)| weight)).unwrap();

    let mut pool = vec![];

    for _ in 1..100{
        let item = sample_item[weight_dist.sample(&mut rng)];
        pool.push(item.0);
    }
    println!("{:?}", pool.iter().filter(|x| **x == 'a').count());
    println!("{:?}", pool.iter().filter(|x| **x == 'b').count());
    println!("{:?}", pool.iter().filter(|x| **x == 'c').count());
    println!("{:?}", pool.iter().filter(|x| **x == 'd').count());
    println!("{:?}", pool.iter().filter(|x| **x == 'e').count());
    println!("{:?}", pool.iter().filter(|x| **x == 'f').count());
}

您可以试试代码here