//  random.hpp
//  Copyright (C) 2008  Chipset
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as       
//  published by the Free Software Foundation, either version 3 of the    
//  License, or (at your option) any later version. 
//    
//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program. If not, see <http://www.gnu.org/licenses/>.   
//

#ifndef RANDOM_HPP_
#define RANDOM_HPP_
#include 
<ctime>

class random
{
public:
  
explicit random(unsigned long s = 0) : seed(s)
  {
    
if (0 == seed) seed = std::time(0);
    randomize();
  }
  
void reset(unsigned long s = 0)
  {
    seed 
= s;
    
if (0 == seed) seed = std::time(0);
    randomize();
  }
  unsigned 
long rand()
  {
  
//returns a random integer in the range [0, -1UL)
    randomize();
    
return seed;
  }
  
double real()
  {
  
//returns a random real number in the range [0.0, 1.0)
    randomize();
    
return double(seed) / -1UL;
  }
private:
  unsigned 
long seed;
  
void randomize() { seed = 1103515245UL * seed + 12345UL; }
};

class rand_help
{
  
static random r;
public:
  rand_help() {}
 
void operator()(unsigned long s) { r.reset(s); }
  unsigned 
long operator()() const { return r.rand(); }
 
double operator()(double) { return r.real(); }
};
random rand_help:: r;

extern
void srandom(unsigned long ns = 0) { rand_help()(ns); } //reset seed
extern unsigned long irand() { return rand_help()(); }         //negative numbers disallowed
extern double drand() { return rand_help()(1.0); }             //for real numbers

#endif  // RANDOM_HPP_

//以上隨機(jī)數(shù)產(chǎn)生器產(chǎn)生的隨機(jī)數(shù)比rand()產(chǎn)生的隨機(jī)數(shù)更加隨機(jī)(可以用數(shù)學(xué)方法檢驗(yàn)),
//范圍更大(一目了然),速度更快(測試一下便知,稍加修改我還可以讓它再快一些,如果有必要)。

/*假設(shè)隨機(jī)數(shù)均勻分布為理想分布, 粗略估計(jì)隨機(jī)性*/
#include 
<iostream>
#include 
<vector>
#include 
<iomanip>
#include 
"random.hpp"
int main()
{
  srand(time(
0));
  
//SZ分別取值2^3, 2^4, , 2^15進(jìn)行測試
  const size_t SZ = 1 << 15;
  std::vector
<unsigned> v1(SZ), v3(SZ);
  std::vector
<unsigned> v2(SZ), v4(SZ);
  
for(size_t i = 0; i < SZ; ++i)
  {
    
++v1[rand() % SZ];//對應(yīng)元素計(jì)數(shù) ,理論上v1[0] ~ v1[SZ - 1]之間每個(gè)都應(yīng)該是1
    ++v2[irand() % SZ];
  }

  
for(size_t i = 0; i < SZ; ++i)
  {
    
++v3[v1[i]]; //統(tǒng)計(jì)頻度
    ++v4[v2[i]];
  }
  
//假設(shè)[0, SSZ)之間不存在間斷點(diǎn), (即使有間斷點(diǎn)也無所謂,我們只做粗略模糊統(tǒng)計(jì),因?yàn)闆]有必要那么精確)
  
//最理想的顯示結(jié)果應(yīng)該是0:    0,   1:   SZ,    2:    0,   3:    0,   4:    0,   other:    0
  
//0:表示間斷,1:表示均勻,2:, 3:, 4:, other: 都表示不同程度的重復(fù)
  const size_t SSZ = 5;
  std::cout.fill(
' ');
  
for(size_t i = 0; i < SSZ; ++i)
    std::cout 
<< i << "" << std::setw(SSZ) << v3[i] << ",   ";
  std::cout 
<< "other: " << std::setw(SSZ)
            
<< v3.size() - v3[0- v3[1- v3[2- v3[3- v3[4<< '\n';
  
for(size_t i = 0; i < SSZ; ++i)
    std::cout 
<< i << "" << std::setw(SSZ) << v4[i] << ",   ";
  std::cout 
<< "other: " << std::setw(SSZ)
            
<< v4.size() - v4[0- v4[1- v4[2- v4[3- v4[4<< '\n';
  system(
"pause");
}


//做速度測試
#include <iostream>
#include 
<ctime>
#include 
<cstdlib>
#include 
<windows.h>
#include 
"random.hpp"

int main()
{
  
const size_t SZ = 1 << 27;
  std::cout 
<< "generating random numbers in progress \n";
  std::cout 
<< SZ << " random numbers generated.\n";
  std::cout 
<< "random used: ";
  Sleep(
1000);
  std::clock_t time 
= clock();
  
for(size_t i = 0; i < SZ; ++i)
    irand();
  std::cout 
<< clock() - time << "ms, ";

  std::cout 
<< "rand() used: ";
  Sleep(
1000);
  std::srand(std::time(
0));
  std::clock_t t 
= clock();
  
for(size_t i = 0; i < SZ; ++i)
    std::rand();
  std::cout 
<< clock() - t << "ms\n";

  std::system(
"PAUSE");
  
return 0;
}