为什么不';t这种可重复的随机算法有效

本文关键字:随机 有效 算法 为什么不 | 更新日期: 2023-09-27 18:29:49

我需要得到一个随机生成器,它将两个坐标作为种子,并输出一个随机数,对于相同的坐标总是相同的。因此,受Jon Skeet的GetHashCode实现的启发,以下是我所做的:

public class SimpleRandom2D
{
    public SimpleRandom2D(int _Seed)
    {
        Seed = _Seed;
    }
    public SimpleRandom2D()
    {
        Seed = new Random().Next();
    }
    readonly public int Seed;
    public float Sample(float _X, float _Y)
    {
        int thisSeed;
        unchecked
        {
            thisSeed = (int) 2166136261;
            thisSeed = thisSeed * 16777619 ^ _X.GetHashCode();
            thisSeed = thisSeed * 16777619 ^ _Y.GetHashCode();
            thisSeed = thisSeed * 16777619 ^ Seed;
        }
        return 2f * (float) new Random(thisSeed).NextDouble() - 1f;
    }
}

我知道创建一个新的Random远远不是最佳的,但我想在快速获得它之前先纠正这个问题。然而,事实证明这并不是真正正确的:它有时会为具有相同x且y为±1的坐标返回相同的值。此测试始终失败:

    [Test]
    [Repeat (20)]
    public void Sample_IntegerFloats_WithSameXNeighbourY_NotSame()
    {
        var random = new Random();
        var simpleRandom2d = new SimpleRandom2D();
        float y = random.Next(); // .Next() returns an integer, which is implicitly converted to a float — hence IntegerFloats in the test title
        float x = random.Next();
        float value1 = simpleRandom2d.Sample(x, y);
        float value2 = simpleRandom2d.Sample(x, y + 1);
        Assert.That(value1, Is.Not.EqualTo(value2));
    }

相反,这个测试没有失败:

    [Test]
    [Repeat (20)]
    public void Sample_IntegerFloats_WithSameX_NotSame()
    {
        var random = new Random();
        var simpleRandom2d = new SimpleRandom2D();
        float x = random.Next();
        float value1 = simpleRandom2d.Sample(x, random.Next());
        float value2 = simpleRandom2d.Sample(x, random.Next());
        Assert.That(value1, Is.Not.EqualTo(value2));
    }

为什么会发生这种情况,我该如何解决?

为什么不';t这种可重复的随机算法有效

事实证明,我的错误与随机性本身无关。我用random的.Next()方法生成了一个随机整数浮点。然而,我忘记了,虽然.Next()会产生从0到2147483647的任何整数,但浮点类型的精度有限,所以当我使用+ 1来获取"邻居"时,我的浮点在大多数情况下都太大了,以至于它实际上并不重要。换句话说,当你这样做时:

float x = new Random().Next();
y = x + 1;

x通常仍然等于y。