100 lines
2.5 KiB
C++
Executable File
100 lines
2.5 KiB
C++
Executable File
/*
|
|
* File: random.cpp
|
|
* ----------------
|
|
* This file implements the random.h interface.
|
|
*/
|
|
|
|
#include <cstdlib>
|
|
#include <cmath>
|
|
#include <ctime>
|
|
#include "random.h"
|
|
#include "private/randompatch.h"
|
|
using namespace std;
|
|
|
|
/* Private function prototype */
|
|
|
|
static void initRandomSeed();
|
|
|
|
/*
|
|
* Implementation notes: randomInteger
|
|
* -----------------------------------
|
|
* The code for randomInteger produces the number in four steps:
|
|
*
|
|
* 1. Generate a random real number d in the range [0 .. 1).
|
|
* 2. Scale the number to the range [0 .. N) where N is the number of values.
|
|
* 3. Translate the number so that the range starts at the appropriate value.
|
|
* 4. Convert the result to the next lower integer.
|
|
*
|
|
* The implementation is complicated by the fact that both the expression
|
|
*
|
|
* RAND_MAX + 1
|
|
*
|
|
* and the expression for the number of values
|
|
*
|
|
* high - low + 1
|
|
*
|
|
* can overflow the integer range. These calculations must therefore be
|
|
* performed using doubles instead of ints.
|
|
*/
|
|
|
|
int randomInteger(int low, int high) {
|
|
initRandomSeed();
|
|
double d = rand() / (double(RAND_MAX) + 1);
|
|
double s = d * (double(high) - low + 1);
|
|
return int(floor(low + s));
|
|
}
|
|
|
|
/*
|
|
* Implementation notes: randomReal
|
|
* --------------------------------
|
|
* The code for randomReal is similar to that for randomInteger,
|
|
* without the final conversion step.
|
|
*/
|
|
|
|
double randomReal(double low, double high) {
|
|
initRandomSeed();
|
|
double d = rand() / (double(RAND_MAX) + 1);
|
|
double s = d * (high - low);
|
|
return low + s;
|
|
}
|
|
|
|
/*
|
|
* Implementation notes: randomChance
|
|
* ----------------------------------
|
|
* The code for randomChance calls randomReal(0, 1) and then checks
|
|
* whether the result is less than the requested probability.
|
|
*/
|
|
|
|
bool randomChance(double p) {
|
|
initRandomSeed();
|
|
return randomReal(0, 1) < p;
|
|
}
|
|
|
|
/*
|
|
* Implementation notes: setRandomSeed
|
|
* -----------------------------------
|
|
* The setRandomSeed function simply forwards its argument to srand.
|
|
* The call to initRandomSeed is required to set the initialized flag.
|
|
*/
|
|
|
|
void setRandomSeed(int seed) {
|
|
initRandomSeed();
|
|
srand(seed);
|
|
}
|
|
|
|
/*
|
|
* Implementation notes: initRandomSeed
|
|
* ------------------------------------
|
|
* The initRandomSeed function declares a static variable that keeps track
|
|
* of whether the seed has been initialized. The first time initRandomSeed
|
|
* is called, initialized is false, so the seed is set to the current time.
|
|
*/
|
|
|
|
static void initRandomSeed() {
|
|
static bool initialized = false;
|
|
if (!initialized) {
|
|
srand(int(time(NULL)));
|
|
initialized = true;
|
|
}
|
|
}
|