C #: метод Random.nextDouble останавливает работу приложения

#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 . если мы напишем это таким образом, мы получим видимость «невозможного» условия и сможем что-то с этим сделать, а не просто зацикливаться.