我有一个存储随机数的unsigned int。我需要使用这个数字来生成一系列“随机相似”的数字,如果这个原始的随机数再次出现,它会产生完全相同的数字。
即。
随机数:123456789
首先“随机数字”:3
第二个“随机数字”:7
第三个“随机数字”:1
第四个“随机数字”:9
等等。
下次出现随机数时,需要从中生成完全相同的数字。
非随机数可以复制和/或环绕(如果使用的算法超出数字,则重新开始,它可以从头开始)。只要每次都生成相同的数字。
我意识到这正是rand()所做的(用随机数播种),但是我不能使用rand。因此,或许更简洁的问题是如何复制“迷你”兰特函数(它不必是任何复杂的,只要出现的数字看起来有些随机化)。
此外,我不能使用提升(不幸的是)。
任何指针/提示?
答案 0 :(得分:3)
我完全不知道为什么你不能使用rand
本身,但如果没有,那么你可以自己动手。使用整数为数字设定种子,然后使用标准Xn+1 = a * Xn + c mod m
。
Wikipedia page for linear congruential method包含a
,c
和m
的一些示例值。
现在LCM并不是世界上最大的随机数生成器,但是,如果你只想要“看起来有点随机化”的数字,那就足够了。
作为LCM算法的一个示例,以下函数基于上述链接页面中的Microsoft Visual/Quick C/C++
条目:
// LCM pseudo-random number generator.
// Outputs numbers from 0..32767 inclusive.
// With protection against identical sequences.
// due to full 32-bit cycle but only returning 15 bits.
uint32_t myRand (void) {
const static uint32_t a = 214013U;
const static uint32_t c = 2531011U;
// m is, of course, 2^32 since the values will wrap.
static uint32_t seed = 1;
seed = seed * a + c;
return (seed >> 16) & 0x7FFF;
}
具有32位数字的整个范围的循环时间,但每次只返回种子的某些位,这减少了相同序列的出现。
如果您希望C ++类执行此操作以使所有随机数生成器彼此独立(如TomZ所建议),则可以使用以下内容:
class myRand {
public:
myRand ();
myRand (unsigned int newSeed);
~myRand ();
void setSeed (unsigned int newSeed);
unsigned int getSeed (void);
unsigned int next (void);
private:
unsigned int seed;
const static unsigned int a = 214013U;
const static unsigned int c = 2531011U;
};
myRand::myRand () { seed = 1; }
myRand::myRand (unsigned int newSeed) { setSeed (newSeed); }
myRand::~myRand () { }
void myRand::setSeed (unsigned int newSeed) { seed = newSeed; }
unsigned int myRand::getSeed (void) { return seed; }
unsigned int myRand::next (void) {
seed = (seed * a + c) & 0xffffffff;
return (seed >> 16) & 0x7fff;
}
#include <iostream>
int main (void) {
myRand r (5);
std::cout << r.next() << "\n"; // 54
std::cout << r.next() << "\n"; // 28693
unsigned int saveSeed = r.getSeed();
std::cout << r.next() << "\n"; // 12255
std::cout << r.next() << "\n"; // 24449
r.setSeed (saveSeed);
std::cout << r.next() << "\n"; // 12255
std::cout << r.next() << "\n"; // 24449
return 0;
}
答案 1 :(得分:1)
组合实现线性同余生成器的类:
http://en.wikipedia.org/wiki/Linear_congruential_generator
您可以查找A和C的良好值,并使用2 ^ 32作为M(模数) 数值配方的例子:A = 1664525,C = 1013904223
正如文章所述,使用2 ^ 32作为模数在32位字长上是“免费的”。
这与大多数版本的rand()使用的算法相同。
请注意它不安全。
种子值是x。使用相同的种子将生成相同的序列。
答案 2 :(得分:0)
您可以从<random>
(或<tr1/random>
)中选择任意伪随机数生成引擎,并为其提供统一整数分布。
只要您种子引擎具有相同的数字,结果的整数序列将是相同的。
示例:
#include <random>
std::mt19937 rng; // everyone's favourite engine: fast, long period
std::uniform_int_distribution<uint32_t> uniformUINT32(0, 99); // numbers in the range [0, 100)
int main()
{
static const unsigned long int seed = 123;
rng.seed(seed);
int val;
val = uniformUINT32(rng); // a predictable random number (69)
val = uniformUINT32(rng); // ditto (71)
}
答案 3 :(得分:0)
对于你的情况,你可以使用伪随机数发生器(适合做一些快速的花哨的东西,但不适用于安全/科学相关领域)
Rn = Rn * 1664525 + 1013904223
Rn的数据类型是uint32_t,用于支持类型环绕。 Rn的初始值充当种子。