重新种植std :: rand / c ++ 11 <random>

时间:2016-07-03 17:41:41

标签: c++ c c++11 random

我正在尝试实现一个简单的噪声函数,它接受两个整数,并根据种子和两个参数返回一个随机浮点数。

使用std::mt19937效果很好,但出于某种原因,当我尝试将srandrand()一起使用时,我会重复数字..

  

注意:在循环中使用c ++ 11 seed成员函数非常非常慢。

这里有两个使用两种方法的地形(具有相同的重播数字):

c ++ 11 random:

std::random_device rd;
std::mt19937 g{ rd() };
std::uniform_real_distribution<float> gen{ -1.0, 1.0 };

float getNoise(int x, int z) {
     g.seed(x * 523234 + z * 128354 + seed);
     return gen(g);
}

c++11 random

随机:

float getNoise(int x, int z) {
        std::srand(x * 523234 + z * 128354 + seed);
        return static_cast<float>(std::rand()) / RAND_MAX * 2.0f - 1.0f;
}

enter image description here

问题:

  1. 有没有更快的方法来重新设置c ++ 11伪随机数?
  2. 为什么srand没有按预期工作?
  3. 提前致谢。

    修改 好抱歉不清楚,而且,我知道也许我错了但让我尝试再次解释,我使用重播,因为我在迭代时使用相同的x和z坐标(不是相同的迭代)。

    如果我删除重播,我会得到这个结果: enter image description here

3 个答案:

答案 0 :(得分:6)

  

我正在尝试实现一个简单的噪声函数,它接受两个整数,并根据种子和两个参数返回一个随机浮点数。

     

请不要说我不应该重新种植,我想故意重新种植。

你故意打破它,并问我们为什么它被打破,但需要注意的是我们不允许在房间里提到大猩猩。

不要重新种植。

[编辑]
好的,根据评论请求,这里有一个答案:

1)不,没有更快的方法来重新种植PRNG,无论如何你都不应该这样做。适当地,你应该播种,然后通过丢弃几千个值来“预热”PRNG。

2)原因rand()(并且,即使您不相信它,您使用的任何其他PRNG)也不起作用是因为您的getNoise()功能不正确。

您的第三张图片是正确的。这是应该期望的结果,只需返回一个钳位的随机值。

你试图通过弄乱种子来调节它,并且由于你第一次尝试中的明显视觉上的好处,得出的结论是这是正确的方法。然而,真正发生的事情是你只是削弱了PRNG并看到了结果。 (在rand()尝试中更清楚,因为它的种子更粗略地定义了结果序列,它本身的周期比Mersenne Twister小。)

(尝试通过倾斜(x,z)坐标来修改它也是一个红色的鲱鱼。它不会影响输出的实际随机性。)

<强> TL; DR
你做错了。

如果你想生成地形图,你应该围绕分形地形生成谷歌。事实上,这里有一个不错的链接:http://www.gameprogrammer.com/fractal.html

你会发现它需要做更多的工作,但这些方法非常简单,你可以很容易地调整它们来修改你的结果。

希望这有帮助。

答案 1 :(得分:3)

随机数生成器从初始种子生成随机值的序列,并不意味着用于生成种子函数的单个随机值。所以它应该用g.seed(seed)初始化,然后按所有(x,y)值的固定顺序调用,而不是每次都重新播种。这将有效地提供随机值,并具有预期的分布。

例如:

std::random_device rd;
std::mt19937 g{ rd() };
std::uniform_real_distribution<float> gen{ -1.0, 1.0 };

constexpr std::size_t nx = 100;
constexpr std::size_t nz = 100;
float noise[nx][nz];

void generateNoise() {
     g.seed(seed);
     for(int x = 0; x < nx; ++x) for(int x = 0; x < nx; ++x)
          noise[x][z] = gen(g);
     return gen(g);
}

答案 2 :(得分:2)

我不明白为什么你想要不断重播 - 这似乎毫无意义和缓慢。但那不是你要问的,所以......

  1. rand产生质量非常差的随机数。非常低的周期,通常基于线性同余发生器(不好)。而且,种子大小非常小。不要使用它 - <random>存在是有原因的。

  2. 使用srand进行播种的方式似乎很大程度上取决于您传入的xz值,然后您乘以可能导致的大数字传递给srand时溢出和截断,意味着(由于可能的种子值数量有限),您经常会重复使用相同的种子。

  3. 您可能想要访问的一些相关链接:

    http://en.cppreference.com/w/cpp/numeric/random

    https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful