Мне нужно было получить случайный генератор, который взял бы в двух координатах как семя и вывел бы случайное число, всегда одинаковое для тех же координат. Так, вдохновленный Jon Skeet's GetHashCode implementation, вот что я сделал:Почему этот повторяемый случайный алгоритм не работает?
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 и у которых ± 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));
}
Почему это происходит и как я могу это исправить?
Это не «случайный». Похоже, вы хотите Хешировать двумерную координату. –
Возможно, вы правы - правильный хэш, сам, случайный относительно его семени. Тем не менее, мне нужно было создать его наряду с другими алгоритмами шума, которые будут опираться на него (шум Perlin и т. Д.), Поэтому я решил использовать слово «Random» для ясности. –
Еще один момент: как вы можете проверить параметр 'int _X' с помощью аргумента' float x'? Мы смотрим на настоящий код или нет? –