Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
0 / 0 / 0
Регистрация: 27.03.2016
Сообщений: 33
1

Когда твой Random совсем не Random

20.04.2016, 11:06. Просмотров 2412. Ответов 21
Метки нет (Все метки)


Мой код ведет себя весьма странно. У меня есть список экземпляров класса в котором (Уж простите что я такое наделал) есть экземпляр другого класса с 4-мя переменными которые рандомятся вместе с созданием экземпляра базового класса.
Прилагаю код.
Занесение экземпляров в коллекцию.
C#
1
2
3
4
5
6
7
8
        private void CreateGenomes()
        {
            for (int i = 0; i < m_populationSize ; i++)
            {
                Genome g = new Genome();
                m_thisGeneration.Add(g);
            }
        }
Конструктор и высов метода заполнения полей для базового класса с переменными. Метод CreateGenes принимает фиктивный параметр для создания перегрузки.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        public Genome()
        {
            vars = new Vars();
            CreateGenes(vars);
        }
 
private void CreateGenes(Vars _vars)
        {
            
            Random r = new Random(); //В отладчике эта часть работает нормально
            vars.a = r.Next(1, 30);
            vars.b = r.Next(1, 30);
            vars.c = r.Next(1, 30);
            vars.d = r.Next(1, 30); 
        }
Класс Vars
C#
1
2
3
4
        public class Vars
        {
            public int a, b, c, d;
        }
Если я делаю это в отладчике - значения у этого самого экземпляра var разные. Только я убираю брейкпоинт и все значения становятся одинаковыми!!!! Как это обойти?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.04.2016, 11:06
Ответы с готовыми решениями:

Random, повторы при static Random(1 seed)
Добрый вечер. Использую private static readonly Random, так как крутится в цикле и если убрать...

Что не так с 'Random' или There is no overloaded version of 'Random' that can be called with these arguments
Доброго времени суток! Я с программированием на &quot;Вы&quot;, поэтому очень прошу доходчиво объяснить, что...

У меня непонятки с методами Math.random() и Random()
Задача : заполнить массив из 15 элементов случайным образом вещественными значениями х (-5 &lt;= x &lt;=...

Random и объекты класса (pseudo random)
Всем привет. Есть класс: typedef unsigned int ui; class Player { private: ui health;

21
Заблокирован
20.04.2016, 11:15 2
Цитата Сообщение от vavan194 Посмотреть сообщение
Только я убираю брейкпоинт и все значения становятся одинаковыми!!!!
Как ты это определяешь? Покажи код полностью.
0
737 / 478 / 187
Регистрация: 30.12.2012
Сообщений: 1,275
Записей в блоге: 2
20.04.2016, 11:18 3
Цитата Сообщение от vavan194 Посмотреть сообщение
Как это обойти?
Вынесите инициализацию рандома из цикла.
0
Эксперт .NET
14836 / 11224 / 2946
Регистрация: 17.09.2011
Сообщений: 18,796
20.04.2016, 11:20 4
Лучший ответ Сообщение было отмечено vavan194 как решение

Решение

C#
1
2
3
4
5
6
7
8
static readonly Random r = new Random();
private void CreateGenes(Vars _vars)
        {
            vars.a = r.Next(1, 30);
            vars.b = r.Next(1, 30);
            vars.c = r.Next(1, 30);
            vars.d = r.Next(1, 30); 
        }
Программа не работает правильно без "Console.ReadLine()"
0
1449 / 842 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
20.04.2016, 11:22 5
Цитата Сообщение от vavan194 Посмотреть сообщение
Как это обойти?
Попробуй поставить между операциями Thread.Sleep(1);

Random действительно не совсем рандом. Это псевдорандом.

Он использует время работы системы для расчёта значений.
У тебя все операции успевают сработать за один тик времени. А дебаггером ты создаёшь задержку(время успевает протикать).
0
0 / 0 / 0
Регистрация: 27.03.2016
Сообщений: 33
20.04.2016, 11:25  [ТС] 6
nimazzzy, Очень просто
0-й элемент был отлажен.
0
Миниатюры
Когда твой Random совсем не Random   Когда твой Random совсем не Random   Когда твой Random совсем не Random  

0 / 0 / 0
Регистрация: 27.03.2016
Сообщений: 33
20.04.2016, 11:34  [ТС] 7
LeniumSoft, Hkolorotur, а я смотрю на этот код и думаю - "Что же его заставило сделать рандом отдельным полем класса да еще и статическим???"
C#
1
        static Random m_random = new Random();
Спасибо огромное вам!)

LeniumSoft, попытка почти удалась. Он делал одинаковыми только по 11 элементов а, дальше у него появлялись новые 11 элементов)
0
Эксперт .NET
8639 / 6100 / 1017
Регистрация: 21.01.2016
Сообщений: 23,018
20.04.2016, 11:40 8
Цитата Сообщение от LeniumSoft Посмотреть сообщение
Он использует время работы системы для расчёта значений.
Только для инициализации SEED в конструкторе по умолчанию. Последующие вызовы методов Next() это значение меняют и разрешающая способность таймера здесь не причём. Единственное, на что влияет разрешение часов, так это на создаваемые последовательно объекты Random - если между созданием меньше 15 миллисекунд, то такие рандомайзеры будут выдавать одинаковые последовательности.
1
1449 / 842 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
20.04.2016, 11:45 9
Цитата Сообщение от Usaga Посмотреть сообщение
Только для инициализации SEED в конструкторе по умолчанию.
Да. В курсе. Я не заметил цикл сверху у TC. Думал что методы Next выдают одно значение. Буду внимательнее смотреть отныне
0
Master of Orion
Эксперт .NET
6079 / 4935 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.04.2016, 12:29 10
LeniumSoft, как только человек говорит, что у него "неслучайный рандом", не заходя в тему я знаю, что увижу слово new в цикле. Рандом может быть спрятан, еще что-то, то new будет 100%
2
0 / 0 / 0
Регистрация: 27.03.2016
Сообщений: 33
20.04.2016, 13:08  [ТС] 11
Psilon, похоже что я не первый)
0
Эксперт .NETАвтор FAQ
9836 / 4795 / 1726
Регистрация: 11.01.2015
Сообщений: 5,973
Записей в блоге: 34
20.04.2016, 14:07 12
Цитата Сообщение от vavan194 Посмотреть сообщение
похоже что я не первый)
Да, вы не оригинальны. Если сделать поиск по слову Random в форуме, то там ваша проблема вcтречается чуть реже чем везде

Кстати недавно обнаружил у рандома забавный глюк. Если к нему обращаться из нескольких потоков, то рано или поздно возникает ситуация, когда он начинает стабильно генерировать нули
0
Эксперт .NET
8639 / 6100 / 1017
Регистрация: 21.01.2016
Сообщений: 23,018
20.04.2016, 14:18 13
Storm23, это не глюк, об этом прямо сказано в документации. Правда совсем не очевидно, что так должно быть при многопоточном обращении к Random.
0
1449 / 842 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
20.04.2016, 14:25 14
Цитата Сообщение от Storm23 Посмотреть сообщение
Если к нему обращаться из нескольких потоков, то рано или поздно возникает ситуация, когда он начинает стабильно генерировать нули
Цитата Сообщение от Usaga Посмотреть сообщение
Правда совсем не очевидно, что так должно быть при многопоточном обращении к Random.
Там вроде можно статическое поле с Random пометить атрибутом ThreadStatic
0
Эксперт .NET
8639 / 6100 / 1017
Регистрация: 21.01.2016
Сообщений: 23,018
20.04.2016, 14:29 15
Цитата Сообщение от LeniumSoft Посмотреть сообщение
Там вроде можно статическое поле с Random пометить атрибутом ThreadStatic
Ну да. Можно и lock делать. Просто, если к одному объекту Random обращаться из разных потоков, то его так можно и сломать . И об этом прямо сказано. Может это и правда баг, который не стали фиксить, а просто задокументировали
0
1449 / 842 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
20.04.2016, 14:34 16
Цитата Сообщение от Usaga Посмотреть сообщение
Можно и lock делать.

Не по теме:

Не не. ThreadStatic делает поле индивидуальным для потока. Надо будет только проинициализировать разными значениями сам Random. Не будет межпоточного доступа к экземпляру Random. И ошибки соответственно...

0
Эксперт .NETАвтор FAQ
9836 / 4795 / 1726
Регистрация: 11.01.2015
Сообщений: 5,973
Записей в блоге: 34
20.04.2016, 14:34 17
Цитата Сообщение от Usaga Посмотреть сообщение
Ну да. Можно и lock делать.
Если у меня высокопроизводительное приложение, то делать lock ради рандома - непозволительная роскошь.
Цитата Сообщение от LeniumSoft Посмотреть сообщение
пометить атрибутом ThreadStatic
А вот с ThreadStatic - интерснее. Он просаживает скорость работы?
0
Master of Orion
Эксперт .NET
6079 / 4935 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.04.2016, 14:47 18
Usaga, lock будет блокировать доступ, ThreadStatic просто создаст свой экземпляр для каждого потока. С точки зрения производительности разница разительная.

Обычный Random это примитивный класс с минимумом логики (и следовательно оверхеда). Для сколько-нибудь серьезных приложений используются криптографические рандомайзеры. Тем более, что зачастую нужно не равномерное, а нормальное или еще какое распределение. Их можно и самому сделать, если слегка с теорией ознакомиться, но из коробки и быстрее, и лучше, и надежнее.

Короче, рандом - это класс для лабораторок в универе и прототипов на коленке В серьезных приложениях он почти не используется.

Добавлено через 1 минуту
Storm23, да я выше написал. Довольно полезный атрибут. Например одна из возможных имплементаций с SO:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ThreadSafeRandom
{
    private static readonly Random _global = new Random();
    [ThreadStatic] private static Random _local;
 
    public ThreadSafeRandom()
    {
        if (_local == null)
        {
            int seed;
            lock (_global)
            {
                seed = _global.Next();
            }
            _local = new Random(seed);
        }
    }
    public int Next()
    {
        return _local.Next();
    }
}
Добавлено через 8 минут
Правда я бы реализовывал по-другому (с double-check locking легко напутать, например в приведенном выше коде есть баг), например так:
C#
1
2
3
4
5
6
    public class ThreadSafeRandom
    {
        private static readonly ThreadLocal<Random> LocalRandom = new ThreadLocal<Random>(() => new Random(Environment.TickCount ^ 397*Thread.CurrentThread.ManagedThreadId));
 
        public static Random Instance => LocalRandom.Value;
    }
2
Эксперт .NET
8639 / 6100 / 1017
Регистрация: 21.01.2016
Сообщений: 23,018
20.04.2016, 15:07 19
Я понимаю разницу между локом и ThreadStatic. Просто имел в виду, что без синхронизации доступа к этому Random обращаться нельзя.
0
Эксперт .NETАвтор FAQ
9836 / 4795 / 1726
Регистрация: 11.01.2015
Сообщений: 5,973
Записей в блоге: 34
20.04.2016, 15:19 20
Цитата Сообщение от Psilon Посмотреть сообщение
Правда я бы реализовывал по-другому
Только вы [ThreadStatic] где-то посеяли.

Но меня интересует механизм работы. Похоже оно хранит эту статическую переменную где-то в локальной памяти потока? Есть ли разница во времени доступа к полю с атрибутом ThreadStatic и без этого атрибута?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.04.2016, 15:19

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.

Переделать Math.random() в random()
public static void CompMove() { int x = (int) (Math.random() * 3), y = (int) (Math.random() *...

Random корректно работает только когда ему дают "одуматься"
Доброго времени суток! При написании тестового приложения возникла проблема : есть класс circ...

Как узнать когда приходили на твой сайт поисковики
Все привет. Ребята, как вы смотрите, когда на ваших сайтах были поисковики? Когда конкретно они...

Регистация собственного проекта в сети Что делать после того, когда твой проект готов???
Здравствуйте! Есть web-сайт(cделанный собственноручно) LAMP(Linux, Apache, PHP, MySQL) объемы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.