mirror of
https://github.com/raysan5/raylib.git
synced 2025-12-18 12:25:29 +00:00
REVIEWED: GetRandomValue(), explained the new approach to get more uniform random values range
This commit is contained in:
14
src/rcore.c
14
src/rcore.c
@@ -1743,20 +1743,23 @@ int GetRandomValue(int min, int max)
|
|||||||
TRACELOG(LOG_WARNING, "Invalid GetRandomValue() arguments, range should not be higher than %i", RAND_MAX);
|
TRACELOG(LOG_WARNING, "Invalid GetRandomValue() arguments, range should not be higher than %i", RAND_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: This one-line approach produces a non-uniform distribution,
|
||||||
|
// as stated by Donald Knuth in the book The Art of Programming, so
|
||||||
|
// using below approach for more uniform results
|
||||||
|
//value = (rand()%(abs(max - min) + 1) + min);
|
||||||
|
|
||||||
|
// More uniform range solution
|
||||||
int range = (max - min) + 1;
|
int range = (max - min) + 1;
|
||||||
|
|
||||||
// Degenerate/overflow case: fall back to min (same behavior as "always min" instead of UB)
|
// Degenerate/overflow case: fall back to min (same behavior as "always min" instead of UB)
|
||||||
if (range <= 0)
|
if (range <= 0) value = min;
|
||||||
{
|
|
||||||
value = min;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Rejection sampling to get a uniform integer in [min, max]
|
// Rejection sampling to get a uniform integer in [min, max]
|
||||||
unsigned long c = (unsigned long)RAND_MAX + 1UL; // number of possible rand() results
|
unsigned long c = (unsigned long)RAND_MAX + 1UL; // number of possible rand() results
|
||||||
unsigned long m = (unsigned long)range; // size of the target interval
|
unsigned long m = (unsigned long)range; // size of the target interval
|
||||||
unsigned long t = c - (c%m); // largest multiple of m <= c
|
unsigned long t = c - (c%m); // largest multiple of m <= c
|
||||||
unsigned long r;
|
unsigned long r = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@@ -1764,7 +1767,6 @@ int GetRandomValue(int min, int max)
|
|||||||
if (r < t) break; // Only accept values within the fair region
|
if (r < t) break; // Only accept values within the fair region
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
value = min + (int)(r%m);
|
value = min + (int)(r%m);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user