C# 为什么';这种可重复的随机算法不起作用吗?

C# 为什么';这种可重复的随机算法不起作用吗?,c#,random,C#,Random,我需要得到一个随机生成器,它将两个坐标作为种子,并输出一个随机数,对于相同的坐标总是相同的。受此启发,我做了如下工作: public class SimpleRandom2D { public SimpleRandom2D(int _Seed) { Seed = _Seed; } public SimpleRandom2D() { Seed = new Random().Next(); } readonl

我需要得到一个随机生成器,它将两个坐标作为种子,并输出一个随机数,对于相同的坐标总是相同的。受此启发,我做了如下工作:

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;
    }

}
我知道创建一个新的随机变量远远不是最优的,但我想在快速得到它之前先把它弄对。然而,结果证明它并不是真的正确:它有时会返回相同的值,用于具有相同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));
    }

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

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

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

x通常仍然等于y。

这不是“随机的”。看起来你想散列一个二维坐标。另外一点,你怎么能用一个
float X
参数测试
int\ux
参数呢?我们是不是在看真正的代码?@thumbmunkeys这里是:thisSeed=thisSeed*16777619^Seed;我不认为这是您的问题,但仅供参考,
.GetHashCode()
不能保证在程序的多次运行中为相同的输入生成相同的输出。它当前将始终生成相同的,但这是一个实现细节,可能会在已安装的.NET版本之间发生变化。我之所以提出这个问题,是因为您提到序列化生成器。@golergka只要使用GetHashCode并将其放入您自己的代码中就不难了。这样,您就可以保证实现,但这并不是此代码的唯一问题。您需要“确定性随机性”,因此可以(应该)完全消除随机实例,只需编写一个简单的(散列)函数。