#c# #.net #visual-studio #random #mono
#c# #.net #visual-studio #Случайный #моно
Вопрос:
Я получаю некоторое непоследовательное поведение от Random.NextDouble()
.
Регулярно консоль зависала, и загрузка процессора резко увеличивалась, пока я не закрывал ее. Я запустил отладчик и обнаружил, что причиной зависания было Random.NextDouble()
. Я добавил несколько строк для целей отладки, но код выглядит следующим образом:
double generateCatenationRate()
{
double catenation = 999.999; //random value to see if it pops up down there
double uniformValue;
double int_covalence = covalence.original;
double dist = int_covalence - 4;
int counter = 0;
while (true)
{
counter ;
uniformValue = utils.getRandomDouble(); //goes bad here!
if (uniformValue <= 0.15)
{
catenation = Math.Abs(utils.normalize(dist, 0, 4)) uniformValue;
if (catenation < 0 || catenation > 1)
{
if (counter > 10000)
{
Console.WriteLine("Went nuclear!");
break; //break so console doesn't stall out
}
continue;
}
else
{
break;
}
}
}
Console.WriteLine("Took " counter " iterations.");
return 1 - catenation;
}
И:
public static double getRandomDouble()
{
Init();
return random.NextDouble();
}
Наконец:
private static void Init()
{
if (random == null) random = new Random();
}
Обычно он не останавливается, но запуск его несколько раз подряд приводит к таким результатам, как:
Took 4 iterations.
Took 3 iterations
Took 3 iterations.
Took 23 iterations.
Took 12 iterations.
Took 4 iterations.
Went nuclear!
Took 10007 iterations.
Кто-нибудь может объяснить, почему Random.NextDouble()
иногда кажется, что создается бесконечный цикл? Оглядываясь вокруг, я подозреваю, что это как-то связано с тем, как заполняются значения, но любая информация будет оценена; хотелось бы исправить эту проблему.
Спасибо!
РЕДАКТИРОВАТЬ: covalence.original
всегда является целым числом от 1 до 8 (включительно). normalize()
выполняет нормализацию min-max, создавая число от 0 до 1 на основе входных данных и диапазона. Однако ни один из них, похоже, не способствует решению проблемы.
Комментарии:
1. Что делает ваш
normalize()
метод?2. И в чем ценность
covalence.original
?3. Вы можете использовать отладчик (установите точку останова в
Console.WriteLine("Went nuclear!");
строке, чтобы проверить значенияdist
иcatenation
и, возможно, найти недостаток в вашем методе.4. Извините за это — см. Правки
5. Почему бы не вывести значение
uniformValue
, когда вы это сделаетеConsole.WriteLine("Went nuclear!");
? Тогда вы будете знать, с помощью чего его тестировать в отладчике.
Ответ №1:
Если я правильно понимаю, то значение dist
and utils.normalize(dist, 0, 4)
никогда не меняется.
Итак, если int_covalence = 8
тогда dist = 4
и utils.normalize(dist, 0, 4) = 1
, правильно?
Поскольку вероятность генерации 0.0
довольно мала, это catenation
практически всегда будет больше, чем 1
и проверка if (catenation < 0 || catenation > 1)
всегда будет истинной.
Комментарии:
1. Я пропустил некоторый код, но
dist = 4
ровно в 12% случаев, поэтому иногда я просто не замечал этого всякийutils.normalize(dist, 0, 4) = 1
раз, когда он взрывался. Спасибо, что указали на это — мне нужно прекратить попытки программирования после 1 часа ночи :/
Ответ №2:
почему бы просто не генерировать выборки напрямую, а не использовать выборку отклонения?
public static double generateCatenationRate(Random rng, double coval_norm) {
double low = Math.abs(coval_norm) 0.15;
double delta = 1. - low;
if (delta < 0) {
throw new IllegalArgumentException("impossible given covalence");
}
return low delta * rng.nextDouble();
}
откуда coval_norm
все, что вы получаете utils.normalize
. если мы напишем это таким образом, мы получим видимость «невозможного» условия и сможем что-то с этим сделать, а не просто зацикливаться.