在 C/C++ 中获取大随机数
Getting big random numbers in C/C++
标准 rand()
函数给出的数字对我来说不够大:我需要 unsigned long long
个。我们如何获得真正大的随机数?我尝试修改一个简单的哈希函数,但它太 大 ,需要太长时间 运行 并且永远不会产生小于 1e5!!
的数字
您可以使用 std::uniform_int_distribution<unsigned long long>
轻松做到这一点。
简单示例代码(取自here,修改为使用unsigned long long
):
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<unsigned long long> dis(lowerBorder, upperBorder);
for (int n=0; n<10; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
请注意,此处用于演示目的的梅森扭曲器的播种并不完美,例如请参见 here。
这是一个便携式 C99 解决方案,returns 一个随机的 64 位数字:
unsigned long long llrand() {
unsigned long long r = 0;
for (int i = 0; i < 5; ++i) {
r = (r << 15) | (rand() & 0x7FFF);
}
return r & 0xFFFFFFFFFFFFFFFFULL;
}
说明:rand()
returns 0 到 RAND_MAX
和 RAND_MAX
范围内的整数只能保证至少为 32,767(15 个随机位)。 long long
保证有 64 位,但可能更大。
您没有要求特定的 OS 并且这里的答案非常好,但是在 Linux 上(也可能在其他 OSes 上)您也可以阅读来自随机设备。
示例:
#include <stdio.h>
#include <assert.h>
#define RANDDEV "/dev/urandom"
unsigned long long bigrand(void) {
FILE *rdp;
unsigned long long num;
rdp = fopen(RANDDEV, "rb");
assert(rdp);
assert(fread(&num, sizeof(num), 1, rdp) == 1);
fclose(rdp);
return num;
}
在手机上写的,可能有错误。 :P
如果您只想从 rand() 返回的值生成 unsigned long long 并且不关心结果的特征,请考虑以下必须与编译器版本和平台无关的函数(因为没有 "magic numbers"):
// this header has RAND_MAX value
#include <stdlib.h>
// and this header has ULLONG_MAX
#include <limits.h>
unsigned long long ullrand()
// Produces pseudo-random numbers from 0 to ULLONG_MAX
// by filling all bits of unsigned long long integer number
// with bits of several "small" integer numbers generated by rand()
{
unsigned long long myrndnum = 0; // at the beginning just zero
unsigned long long counter = ULLONG_MAX; // at the beginning we have all bits set as 1
// ... and while at least one bit is still set to 1
while(counter > 0) {
myrndnum = (myrndnum * (RAND_MAX + 1)) + rand(); // fill some bits from rand()
counter /= (RAND_MAX + 1); // decrease number of 1-bits in counter
}
// Return the result
return myrndnum;
}
但是如果您想要一些具有某些预定特征的随机数序列,您应该查看一些特定的指南或数学书籍。例如。 https://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html
试试这个:
long N=1000000;
long randNumber;
for(long i=0;i<N;i++)
randNumber=i+rand()
您还可以使用 boost 库(取自 link):
#include <ctime> // std::time
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/generator_iterator.hpp>
int main()
{
long long my_min = 1;
long long my_max = 1e5;
boost::mt19937 generator(static_cast<unsigned int>(std::time(0)));
boost::variate_generator<boost::mt19937&, boost::uniform_real<> >
die_gen(generator, boost::uniform_real<> (my_min, my_max));
boost::generator_iterator<boost::variate_generator<boost::mt19937&, boost::uniform_real<> > > die(&die_gen);
std::cout<<"Generated random numbers: \n";
for (int i=0; i <10 ; i++)
{
std::cout<< static_cast<long long>(*die++) << std::endl;
}
return 0;
}
标准 rand()
函数给出的数字对我来说不够大:我需要 unsigned long long
个。我们如何获得真正大的随机数?我尝试修改一个简单的哈希函数,但它太 大 ,需要太长时间 运行 并且永远不会产生小于 1e5!!
您可以使用 std::uniform_int_distribution<unsigned long long>
轻松做到这一点。
简单示例代码(取自here,修改为使用unsigned long long
):
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<unsigned long long> dis(lowerBorder, upperBorder);
for (int n=0; n<10; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
请注意,此处用于演示目的的梅森扭曲器的播种并不完美,例如请参见 here。
这是一个便携式 C99 解决方案,returns 一个随机的 64 位数字:
unsigned long long llrand() {
unsigned long long r = 0;
for (int i = 0; i < 5; ++i) {
r = (r << 15) | (rand() & 0x7FFF);
}
return r & 0xFFFFFFFFFFFFFFFFULL;
}
说明:rand()
returns 0 到 RAND_MAX
和 RAND_MAX
范围内的整数只能保证至少为 32,767(15 个随机位)。 long long
保证有 64 位,但可能更大。
您没有要求特定的 OS 并且这里的答案非常好,但是在 Linux 上(也可能在其他 OSes 上)您也可以阅读来自随机设备。
示例:
#include <stdio.h>
#include <assert.h>
#define RANDDEV "/dev/urandom"
unsigned long long bigrand(void) {
FILE *rdp;
unsigned long long num;
rdp = fopen(RANDDEV, "rb");
assert(rdp);
assert(fread(&num, sizeof(num), 1, rdp) == 1);
fclose(rdp);
return num;
}
在手机上写的,可能有错误。 :P
如果您只想从 rand() 返回的值生成 unsigned long long 并且不关心结果的特征,请考虑以下必须与编译器版本和平台无关的函数(因为没有 "magic numbers"):
// this header has RAND_MAX value
#include <stdlib.h>
// and this header has ULLONG_MAX
#include <limits.h>
unsigned long long ullrand()
// Produces pseudo-random numbers from 0 to ULLONG_MAX
// by filling all bits of unsigned long long integer number
// with bits of several "small" integer numbers generated by rand()
{
unsigned long long myrndnum = 0; // at the beginning just zero
unsigned long long counter = ULLONG_MAX; // at the beginning we have all bits set as 1
// ... and while at least one bit is still set to 1
while(counter > 0) {
myrndnum = (myrndnum * (RAND_MAX + 1)) + rand(); // fill some bits from rand()
counter /= (RAND_MAX + 1); // decrease number of 1-bits in counter
}
// Return the result
return myrndnum;
}
但是如果您想要一些具有某些预定特征的随机数序列,您应该查看一些特定的指南或数学书籍。例如。 https://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html
试试这个:
long N=1000000;
long randNumber;
for(long i=0;i<N;i++)
randNumber=i+rand()
您还可以使用 boost 库(取自 link):
#include <ctime> // std::time
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/generator_iterator.hpp>
int main()
{
long long my_min = 1;
long long my_max = 1e5;
boost::mt19937 generator(static_cast<unsigned int>(std::time(0)));
boost::variate_generator<boost::mt19937&, boost::uniform_real<> >
die_gen(generator, boost::uniform_real<> (my_min, my_max));
boost::generator_iterator<boost::variate_generator<boost::mt19937&, boost::uniform_real<> > > die(&die_gen);
std::cout<<"Generated random numbers: \n";
for (int i=0; i <10 ; i++)
{
std::cout<< static_cast<long long>(*die++) << std::endl;
}
return 0;
}