【问题标题】:Generating the same random number? [closed]生成相同的随机数? [关闭]
【发布时间】:2015-03-08 19:53:06
【问题描述】:

如何根据xyseed 值生成相同的随机数?因此,如果您一直为xyseed 选择完全相同的值,则从0.01.0 将始终返回相同的float。比如:

//Returns value from 0.0 to 1.0
public static float random(int seed, int x, int y) {
    ...
    return rand;
}

编辑: 我想我找到了一种可以完成这项工作的方法(对不起,如果我问错了问题):

public static float random(int x, int y) {
    int n = x + y * 57;
    n = (n << 13) ^ n;
    return Math.abs((1.0f - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7FFFFFFF) / 1073741824.0f));
}

【问题讨论】:

  • 你想用它做什么?
  • 三个值生成相同的数字不是生成随机数
  • @starblue 用于地形生成,因此值需要始终相同
  • "不使用 new Random()" 你在问如何实现自己的伪随机数生成器吗?如果是这样,请阅读Wikipedia
  • @Blam 这种事情就是伪随机生成器的用途:具有类似随机分布的可重复结果。只需将所有三个输入视为同一种子的一部分。 OP 应该发布询问伪随机生成器而不是随机生成器的问题,但我认为这是分裂的头发(此外,并不是每个人都知道随机与伪随机)

标签: java random


【解决方案1】:

Random 类是一个伪随机序列生成器,这意味着如果您使用相同的种子对其进行初始化,它将返回完全相同的序列。所以用你的参数组合初始化Random并请求一个新的浮点数。

public static float random(int seed, int x, int y) {
    long superSeed = (seed << 32) ^ (x << 16) ^ y; // combine into a single long
    return new Random(superSeed).nextFloat();
}

更新

如果我可以将您的问题解释为:“我怎样才能始终从种子生成相同的地形(使用一个新的 Random() 调用?”,那么我会使用这样的东西:

public static float[][] randomTerrain(long seed, int w, int h) {
    Random random = new Random(seed);
    float[][] terrainRandom = new float[w][h];
    for (int x = 0; x < w; x += 1) {
        for (int y = 0; y < h; y += 1) {
            terrainRandom[x][y] = random.nextFloat();
        }
    }
    return terrainRandom;
}

这将每次都从同一个种子生成相同的随机数组。

这会将随机性存储在一个数组中,但您实际上可以将其集成到您的地形生成代码中,这样您就不必在使用它之前先存储整个数组。

【讨论】:

  • 是的,这就是我要找的。 new Random() 除外。我会经常调用这个方法,所以我不希望每秒分配数百次。
  • 没有办法绕过它,除非您可以接受在整个地形上播种一次的事实。我会更新我的答案。
  • 那么,Random类是如何生成数字的呢?也许复制该方法可能是一种解决方法?我可以阻止它生成“下一个”int。
  • 您不必复制它,因为您可以使用Random 类。构造一次new Random(seed) 并继续向它请求nextFloat()。诀窍是始终以相同的顺序请求它们。
  • 顺便说一句,如果您可以展示使用您的地形生成代码,我们可以帮助您为您整合种子随机性。
【解决方案2】:

取决于 x 和 y 的取值范围。在您的情况下,您有两个 ints,它们确实适合 Random() 种子的 long

简单的情况如下: 对于相同的 x+y,它将返回 0..1 范围内的相同浮点数。但是,它也可能为不同的组合返回相同的浮点数。

long seed = ((long)x << 32) + y;
Random r = new Random(seed);
r.nextLong(); // discard
return r.nextFloat();

内部随机将 64bit long 减少到 48bit 状态。我会添加 r.nextLong() 调用只是为了确保你没有得到前几个字节which are biased

【讨论】:

  • 我已经有了种子,以及 x 和 y 值,我需要结合 x、y 和种子值来创建一个从 0.0 到 1.0 的随机数。
  • 你的问题没有提到你拥有的种子。它有什么功能?您可以将其异或到上述种子。
【解决方案3】:

Math.sin(seed + x + y) 怎么样?

【讨论】:

  • 如果种子为零,那将一直返回零。
  • @name 它仍然达到了既定目标。
  • @Blam 除了它不再是随机的,所以不,它不是
  • @name 不是您想要的 - 返回相同的数字吗?好的,我已将其更改为取决于所有三个...
  • @name 一个数字,它总是与您要求的相同,无论如何都不是随机的。随机数是随机的,因为它们无法预测。 到底怎么称呼“随机”数字?
【解决方案4】:

使用加法、异或 (^) 和大素数乘法的某种组合来组合 seedxy 和一些大常数以获得随机整数。然后将此整数缩放为所需范围内的浮点数。

请注意,随机数的质量取决于这些值的精确选择。如果您想要高质量的随机数,则需要使用 Diehard 测试之类的方法对其进行测试,并调整常数直到质量足够好。

此外,由于这些操作是线性的,聪明的对手可能会在看到其中一些随机数后预测您的随机数。如果这是一个问题,您应该改用一些加密算法来组合 xy 以及一个密钥。

【讨论】:

  • 是的,这似乎与我曾经看到的相似。谢谢,我会搞砸一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
  • 2016-09-02
相关资源
最近更新 更多