Question:
Run some experiments to determine the distribution of numbers returned by the new pseudorandom functions from the previous project. Recall that this function returns a double number in the range [0, 1). Divide this range into 10 intervals, and call the function one million times, producing a table such as this:
Range | Number of Occurrences |
---|---|
[0.0, 0.1) | 99889 |
[0.1, 0.2) | 100309 |
[0.2, 0.3) | 100070 |
[0.3, 0.4) | 99940 |
[0.4, 0.5) | 99584 |
[0.5, 0.6) | 100028 |
[0.6, 0.7) | 99669 |
[0.7, 0.8) | 100100 |
[0.8, 0.9) | 100107 |
[0.9, 1.0) | 100304 |
Run your experiment for different values of the multiplier, increment, and modulus. With good choices of the constants, you will end up with about 10%10\%10% of the numbers in each interval. A pseudorandom number generator with this equal-interval behavior is called uniformly distributed.
My answer:
修改main.cpp
#include "random.h"
#include <iostream>
#include <iomanip>
#include <cassert>
using namespace std;
const int NUM = 10;
enum Range{
R1, R2, R3, R4, R5, R6, R7, R8, R9, R10
};
unsigned int range[NUM] = {0};
void update_list(double r);
void print_list();
int main(){
pseudorandom_generator a(40, 725, 729, 1);
cout << "Test 1: multiplier = 40, increment = 725, modulus = 729, seed = 1" << endl;
int i = 0;
while(i < 1000000){
// a.generate_number();
double r = a.generate_double_number();
update_list(r);
i++;
}
print_list();
pseudorandom_generator b(35, 899, 938, 37);
cout << "Test 2: multiplier = 35, increment = 899, modulus = 1038, seed = 1" << endl;
i = 0;
for(int j = R1; j <= R10; j++){
range[j] = 0;// reinitialize
}
while(i < 1000000){
// a.generate_number();
double r = b.generate_double_number();
update_list(r);
i++;
}
print_list();
return 0;
}
void update_list(double r){
if(r >= 0 && r < 0.1){
range[R1] += 1;
} else if(r >= 0.1 && r < 0.2){
range[R2] += 1;
} else if(r >= 0.2 && r < 0.3){
range[R3] += 1;
} else if(r >= 0.3 && r < 0.4){
range[R4] += 1;
} else if(r >= 0.4 && r < 0.5){
range[R5] += 1;
} else if(r >= 0.5 && r < 0.6){
range[R6] += 1;
} else if(r >= 0.6 && r < 0.7){
range[R7] += 1;
} else if(r >= 0.7 && r < 0.8){
range[R8] += 1;
} else if(r >= 0.8 && r < 0.9){
range[R9] += 1;
} else if(r >= 0.9 && r < 1.0){
range[R10] += 1;
}
}
void print_list(){
cout << "------------------------------------" << endl;
cout << setiosflags(ios::left) << setw(14) << "Range" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << "Number of Occurrences" << resetiosflags(ios::right) << endl;
cout << "------------------------------------" << endl;
for(int i = R1; i <= R10; i++){
switch(i){
case R1:
cout << setiosflags(ios::left) << setw(14) << "[0.0, 0.1)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R1] << resetiosflags(ios::right) << endl;
break;
case R2:
cout << setiosflags(ios::left) << setw(14) << "[0.1, 0.2)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R2] << resetiosflags(ios::right) << endl;
break;
case R3:
cout << setiosflags(ios::left) << setw(14) << "[0.2, 0.3)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R3] << resetiosflags(ios::right) << endl;
break;
case R4:
cout << setiosflags(ios在这里插入代码片::left) << setw(14) << "[0.3, 0.4)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R4] << resetiosflags(ios::right) << endl;
break;
case R5:
cout << setiosflags(ios::left) << setw(14) << "[0.4, 0.5)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R5] << resetiosflags(ios::right) << endl;
break;
case R6:
cout << setiosflags(ios::left) << setw(14) << "[0.5, 0.6)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R6] << resetiosflags(ios::right) << endl;
break;
case R7:
cout << setiosflags(ios::left) << setw(14) << "[0.6, 0.7)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R7] << resetiosflags(ios::right) << endl;
break;
case R8:
cout << setiosflags(ios::left) << setw(14) << "[0.7, 0.8)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R8] << resetiosflags(ios::right) << endl;
break;
case R9:
cout << setiosflags(ios::left) << setw(14) << "[0.8, 0.9)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R9] << resetiosflags(ios::right) << endl;
break;
case R10:
cout << setiosflags(ios::left) << setw(14) << "[0.9, 1.0)" << resetiosflags(ios::left)
<< setiosflags(ios::right) << setw(9) << range[R10] << resetiosflags(ios::right) << endl;
break;
}
}
}
结果:
Test 1: multiplier = 40, increment = 725, modulus = 729, seed = 1
------------------------------------
Range Number of Occurrences
------------------------------------
[0.0, 0.1) 100137
[0.1, 0.2) 100145
[0.2, 0.3) 100136
[0.3, 0.4) 100138
[0.4, 0.5) 100138
[0.5, 0.6) 100138
[0.6, 0.7) 100137
[0.7, 0.8) 100129
[0.8, 0.9) 100138
[0.9, 1.0) 98764
Test 2: multiplier = 35, increment = 899, modulus = 1038, seed = 1
------------------------------------
Range Number of Occurrences
------------------------------------
[0.0, 0.1) 75757
[0.1, 0.2) 121213
[0.2, 0.3) 121211
[0.3, 0.4) 90907
[0.4, 0.5) 90908
[0.5, 0.6) 75758
[0.6, 0.7) 121211
[0.7, 0.8) 121213
[0.8, 0.9) 90912
[0.9, 1.0) 90910
第二个例子似乎和均匀分布相去甚远,是参数选取的问题吗?
Reference:
整理自 Data Structures and Other Objects Using C++ ( Fourth Edition ) Michael Main, Walter Savitch. p124