Created
October 19, 2015 10:23
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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