找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1980|回复: 0

[分享] a better random generator

[复制链接]
发表于 2013-6-1 23:21:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
a better random generator                 //  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_

//以上随机数产生器产生的随机数比rand()产生的随机数更加随机(可以用数学方法检验),
//范围更大(一目了然),速度更快(测试一下便知,稍加修改我还可以让它再快一些,如果有必要)。

/*假设随机数均匀分布为理想分布, 粗略估计随机性*/
#include <iostream>
#include <vector>
#include <iomanip>
#include "random.hpp"
int main()
{
  srand(time(0));
  //SZ分别取值2^3, 2^4, 0.jpg , 2^15进行测试
  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];//对应元素计数 ,理论上v1[0] ~ v1[SZ - 1]之间每个都应该是1
    ++v2[irand() % SZ];
  }

  for(size_t i = 0; i < SZ; ++i)
  {
    ++v3[v1]; //统计频度
    ++v4[v2];
  }
  //假设[0, SSZ)之间不存在间断点, (即使有间断点也无所谓,我们只做粗略模糊统计,因为没有必要那么精确)
  //最理想的显示结果应该是0:    0,   1:   SZ,    2:    0,   3:    0,   4:    0,   other:    0
  //0:表示间断,1:表示均匀,2:, 3:, 4:, other: 都表示不同程度的重复
  const size_t SSZ = 5;
  std::cout.fill(' ');
  for(size_t i = 0; i < SSZ; ++i)
    std::cout << i << ": " << std::setw(SSZ) << v3 << ",   ";
  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 << ",   ";
  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 1.jpg \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;
}


论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-11-22 06:02 , Processed in 0.360485 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表