rust-random / rand

A Rust library for random number generation.
https://crates.io/crates/rand
Other
1.67k stars 431 forks source link

API Design Question: why does `Rng::gen_range` exist, rather than `impl Distribution<Range<T>>` ? #1321

Closed nathan-at-least closed 1 year ago

nathan-at-least commented 1 year ago

This is an API design question (which I would typically ask in a github "Discussions area" if it were enabled). If this is an inappropriate location, let me know a better place to ask.

Why does Rng::gen_range exist, rather than sampling a std::ops::Range from a Distribution type?

The API I imagine that seems less surprising given Distribution is:

struct Uniform;

impl Distribution<Range<i64>> for Uniform { ... }

It also seems like gen_range only supports uniform distributions within a range, whereas the Distribution<Range> approach could support arbitrary distributions over ranges.

I am not well-versed in stats/probability, so I wouldn't be surprised if I have some conceptual gap about this API approach. I'm also wondering if this is just a legacy (e.g. older rand didn't have Distribution or older std didn't have the Range* types).

dhardy commented 1 year ago

The answer is partly historical, but mostly that we have two variants of range sampling: when you want to construct a sampler to use many times, and when you just want to sample that range once.

You can do this:

let dice = Uniform::from(1..=6);
let num_sixes = dice.sample_iter(rand::thread_rng())
    .take(100)
    .filter(|x| *x == 6)
    .count();
println!("Number of sixes: {}", num_sixes);

(Of course, you can also do that with a Binomial distribution.)

vks commented 1 year ago

Range is not a good replacement for the uniform distribution struct, because we store the transformed values optimized for sampling. This reduces the work required when sampling many times.

This applies to most distributions: We usually store some transformation of the input values.

Converting a Range to a uniform distribution is possible, as @dhardy showed.

nathan-at-least commented 1 year ago

Thanks for the explanations!