Skip to content

Instantly share code, notes, and snippets.

@goldsborough
Created October 19, 2015 10:23
Show Gist options
  • Save goldsborough/cd8ca68f6c1b776f3b9f to your computer and use it in GitHub Desktop.
Save goldsborough/cd8ca68f6c1b776f3b9f to your computer and use it in GitHub Desktop.
Generate a random value in one range given a function to generate a uniformly-random number from another range.
std::size_t random_for_random(const std::pair<std::size_t, std::size_t>& base_range,
const std::function<std::size_t(void)>& base_function,
const std::pair<std::size_t, std::size_t>& target_range)
{
// The number of values in the base range
const std::size_t base_size = base_range.second - base_range.first + 1;
// The number of values in the target range
const std::size_t target_size = target_range.second - target_range.first + 1;
// The smallest value we can generate from the base values
const std::size_t minimum = base_size * base_range.first + base_range.first;
// The largest value we can generate from the base values
const std::size_t maximum = base_size * base_range.second + base_range.second;
// The smallest value for the uniform target range
const std::size_t lower_bound = std::ceil(minimum / target_range.second) * target_range.second;
// The largest value for the uniform target range
const std::size_t upper_bound = maximum - (maximum % target_size);
while (true)
{
// Generate a uniform number
auto number = base_size * base_function() + base_function();
// If it is in the range we want, we can return it
// being sure that in this range all values can appear
// with uniform probability
if (number >= lower_bound && number < upper_bound)
{
return number % target_size;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment