【发布时间】:2012-04-29 05:41:14
【问题描述】:
我在我的程序中基于 C++ rand() 函数生成了几千个对象。将它们保存在内存中将是详尽无遗的。有没有办法在任何给定时间复制 rand() 的当前种子?这将使我有机会仅存储当前种子而不是完整对象。 (因此我可以通过重新生成完全相同的随机数子序列来重新生成这些对象)
一个详尽的解决方案是存储 rand() 给出的完整随机数序列 - 不值得。 另一个将是的解决方案是实现我自己的随机数类。
Google 没有给我任何积极的线索。讲 rand 和 srand 基础知识的文章有数百篇,我找不到具体的。
有谁知道其他带有种子窃取器的随机数生成器?
感谢您的快速答复!这个问题有更多可能的答案/解决方案,所以我在这里列出了你的答案。
解决方案:
简短的回答是:没有获取种子的标准方法
-
最接近的解决方法是在开头保存 INITIAL 种子,并计算调用 rand() 函数的次数。我将此标记为解决方案,因为它适用于 每个编译器 的当前 std::rand() 函数(这是主要问题)。我对我的 2.0 GHz CPU 进行了基准测试,发现我可以在 35 秒内调用&count rand() 1,000,000,000 次。这听起来不错,但我有 80,000 次调用来生成一个对象。这将代数限制为 50,000,因为 unsigned long 的大小。无论如何,这是我的代码:
class rand2 { unsigned long n; public: rand2 () : n(0) {} unsigned long rnd() { n++; return rand(); } // get number of rand() calls inside this object unsigned long getno () { return n; } // fast forward to a saved position called rec void fast_forward (unsigned long rec) { while (n < rec) rnd(); } }; 另一种方法是实现您自己的伪随机数生成器,就像 Matteo Italia 建议的那样。这是最快的,也可能是最好的解决方案。您不限于 4,294,967,295 rand() 调用,也不需要使用其他库。值得一提的是,不同的编译器有不同的生成器。我在 Mingw/GCC 3.4.2 和 G++ 4.3.2 中比较了 Matteo 的 LCG 和 rand()。所有 3 个都是不同的(seed = 0)。
按照 Cubbi、Jerry Coffin 和 Mike Seymour 的建议,使用来自 C++11 或其他库的生成器。如果您已经在与他们合作,这是最好的主意。 C++11 生成器的链接:http://en.cppreference.com/w/cpp/numeric/random (这里也有一些算法描述)
【问题讨论】:
-
如果在解决方案 2 中只有计数限制是问题,您可以添加另一个
unsigned long计数器来计算溢出。这将有效地使您的计数器的位大小增加一倍,并且当然可以进一步扩展。 -
顺便说一句,你很高兴添加一个解决方案摘要(旧的 usenet 传统好?)。
-
嘿,不。我实际上不得不用谷歌搜索 usenet 的含义:)。只是觉得提供一些反馈会很好,这些答案很有用。