如何编写可控的随机数发生器?

时间:2012-10-19 02:57:35

标签: c++ boost random

我希望随机数生成可以用变量控制。例如,如果我说100,则应生成具有最大随机性的数字,如果我说50,则数字不应为“随机”。如果我说“0”,可能随机数根本不应该是随机的 - 也许所有生成的数字都是相同的。

知道我可以使用什么来生成像这样的受控随机数?有没有想过是否有一些C ++内置库,或者Boost库可以做到这一点?

有一种方法可以重新生成相同的随机数序列,因此种子生成器的方法也会很好。

6 个答案:

答案 0 :(得分:5)

您描述您的要求的方式似乎表明使用正态分布(也称为高斯分布)可能是要走的路。它有两个参数:平均值和标准偏差。如果将标准偏差设置得非常低,则会得到可能非常接近的随机值。如果将其设置为较大的值,则可以更广泛地分发它们。

在C ++ 11中,可以从标准库中获得正态分布。如果C ++ 11不适合您,Boost库也可以使用它。

以下是一些示例代码:

#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
#include <iomanip>

int main()
{
  std::random_device rd;
  std::mt19937 gen(rd());

  std::cout << std::fixed << std::setprecision(3);

  /* Mean 5, standard deviation very low (0.002): */
  std::normal_distribution<> d1(5,0.002);
  for (int i = 0 ; i < 20 ; ++i)
    std::cout << std::setw(7) << d1(gen) << "  ";
  std::cout << std::endl;

  /* Mean 5, standard deviation relatively high (2.0): */
  std::normal_distribution<> d2(5,2);
  for (int i = 0 ; i < 20 ; ++i)
    std::cout << std::setw(7) << d2(gen) << "  ";
  std::cout << std::endl;

  return 0;
}

这是输出:

4.998    5.003    5.001    5.002    5.001    5.001    4.998    5.000    4.999    5.001    5.000    5.003    4.999    5.000    5.001    4.998    5.000    4.999    4.996    5.001  
2.781    3.795    5.669   -0.109    7.831    3.302    3.823    4.439    4.672    4.461    6.626    5.139    6.882    5.406    6.526    5.831    6.759    2.627    3.918    4.617

正如您所看到的,在第一行中,所有数字都非常接近5(即,使用您的措辞,“随机性”较低),而在第二行中数字的传播范围更广。

(编辑:当然,这些数字的随机性并没有真正受到影响。只是标准偏差参数使得值更可能以更小(stddev low)或更宽的方式出现(stddev high)数字范围。)

答案 1 :(得分:1)

提升has a library以完全按照自己的意愿行事。按照this link到升级教程页面,教你如何进行数字发布。

答案 2 :(得分:1)

有一点XKCD;你可能想要冥想一段时间。实际上没有“随机数”这样的东西,就像没有"an uninteresting number"这样的东西。

你可以要求的是一系列符合某些测试的数字;例如,在任何子序列中,每个值的频率将大致相同,或者序列中的数字与其后继者之间没有相关性。这些测试不能证明序列是“随机的”;只是它可能代表其他这样的序列;也许是在现实世界中出现的序列,除非受un-, sub-, or super-natural forces约束。

在Rosencrantz和Guildenstern简单的硬币翻转序列中,很容易看出有偏见的分布引起了疑虑,甚至是存在性的分歧。但是假设硬币翻转已完全平衡:头部,尾部,头部,尾部,头部,尾部,头部,尾部等等穿过喀尔巴阡山峰。这会或多或少随机吗?正如R(或G)所说,“讨论”。

答案 3 :(得分:1)

首先生成一个随机的位序列。

当旋钮处于100时,单独保留序列。

当旋钮为50时,强制每隔一位为1。

当旋钮为0时,强制每一位为1。

[更新,详细说明]

这个建议并不像听起来那么武断。

真正随机的数据源每位数据有一位熵。如果你想要一半的熵率 - 即每两位数据一位熵 - 你可以将每隔一位设置为1.如果你想要1/3那个速率 - 即每个熵一位三位数据 - 你可以将三位中的每两位设置为1.依此类推。

“每位数据的熵比特”对于数字序列的随机性是一个非常合理的定义......并且当三个比特中的两个是随机的时候调用序列“66%随机”而其他比特是随机的修复是一个非常自然的定义。

答案 4 :(得分:0)

可能最简单的解决方案是在C ++中使用srand和rand,两者都使用伪随机性,srand中的种子值越大,rand生成的随机数中出现模式所需的时间就越多。

编辑:

http://www.cplusplus.com/reference/clibrary/cstdlib/srand/

答案 5 :(得分:0)

r1 = Mathf.PingPong(Mathf.PerlinNoise(map,23)*5+map*.01, 1);

map是随机种子,一个整数,乒乓球反弹0到1之间的所有值,Perlin噪音会产生某种噪音,通过向其添加多个映射,在0和1之间均匀。< / p>