ソースを参照

REVIEWED: `GetRandomValue()`, explained the new approach to get more uniform random values range

pull/5402/head
Ray 1週間前
コミット
bc2057345b
1個のファイルの変更10行の追加8行の削除
  1. +10
    -8
      src/rcore.c

+ 10
- 8
src/rcore.c ファイルの表示

@ -1742,21 +1742,24 @@ 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)
{
value = min;
}
if (range <= 0) 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 r;
unsigned long t = c - (c%m); // largest multiple of m <= c
unsigned long r = 0;
for (;;) for (;;)
{ {
@ -1764,8 +1767,7 @@ 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
return value; return value;

読み込み中…
キャンセル
保存