Генератор случайных чисел без дубликатов

29.12.17

Разработка - Универсальные функции

Хочу рассказать о своем первом опыте работы с Генератором Случайных Чисел без дублей.

Вся проблема в том, что ГенераторСлучайныхЧисел на производительных компьютерах так быстро генерит число, что получается много дубликатов даже в больших числах в конце интервала. Что я имею в виду? Например, мне необходимо было сгенерировать случайным образом 10-ти значные ИНН пусть 20 штук, сделал так:

    

Для н=1 по 20 Цикл
        Код = "";
        Для у=1 по 10 Цикл
            ГСЧ = Новый ГенераторСлучайныхЧисел(ТекущаяУниверсальнаяДатаВМиллисекундах());
            Число = ГСЧ.СлучайноеЧисло(0,9);
            Код = Код + Формат(Число,"ЧЦ=1; ЧН=0; ЧВН=; ЧГ=0");
        КонецЦикла;
        Сообщить(Код);
    КонецЦикла;   

 
 

Результат

5555333333
3333333333
3333333333
3333333333
3444444444
4444444444
4999999999
9999999999
9555555555
5555555555
2222222222
2222222222
6666666666
6666666666
2222222222
2222222222
3333333333
3333333333
1111111111
1111111115

Как видите, получилось много дубликатов. В публикации //infostart.ru/public/553616/ говорится о регистре сведений, в котором все хранится и происходит проверка на наличие дублей, я бы тоже использовал такой вариант при необходимости, но мне просто нужно было нагенерить ИНН, и я использовал Массив, в котором проверяю уже существующие коды

    

Массив = Новый Массив();
    Для н=1 по 20 Цикл
        Найден = Истина;
        Пока Найден Цикл
            ГСЧ = Новый ГенераторСлучайныхЧисел(ТекущаяУниверсальнаяДатаВМиллисекундах());
            Код = "";
            Для у=1 по 10 Цикл
                Число = ГСЧ.СлучайноеЧисло(0,9);
                Код = Код + Формат(Число,"ЧЦ=1; ЧН=0; ЧВН=; ЧГ=0");
            КонецЦикла;
            Результат = Массив.Найти(Код);
            Если Результат=Неопределено Тогда
                Найден = Ложь;
                Массив.Добавить(Код);
            КонецЕсли;    
        КонецЦикла;    
        Сообщить(Код);
    КонецЦикла;    


 

Результат

8043056388
9102338554
6249282932
1198388359
0526412897
7009103148
0571174217
8993611720
3929803898
7864312503
9471210028
0252270828
4561671060
9351136286
3376451113
7216940055
4858606383
3378262630
6057792110
0900779364

 

Может, кому-то поможет!

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Загрузка и выгрузка в Excel Универсальные функции Программист 1С:Предприятие 8 Россия Бесплатно (free)

Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).

30.10.2025    4462    Abysswalker    11    

46

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

Порой необходимо временно отключить расширение 1С, не удаляя его, чтобы не потерять данные. Но в этом случае при каждом запуске всем будет лезть уведомление о неактивном расширении, хотя очевидно, это техническая информация, которой не стоит лишний раз пугать пользователей.

14.05.2025    8251    DeerCven    15    

62

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    55045    dimanich70    84    

174

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    7860    7    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    69717    atdonya    31    

72

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    9830    ke.92@mail.ru    17    

68
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. andrusevich 30.12.17 15:22 Сейчас в теме
Я бы по привычке (с 7.7 начинал) пошел бы списком значений, Отсюда вопрос. Массив быстрее работает чтоли?

И вашем случае я бы чуток по другому сделал

Массив = Новый Массив();

// Незачем в цикле создавать каждый раз
ГСЧ = Новый ГенераторСлучайныхЧисел(ТекущаяУниверсальнаяДатаВМиллисекундах());

Для н=1 по 20 Цикл
        Найден = Истина;
       
        Пока Найден Цикл
            
            // уберем лишний цикл
            Число = ГСЧ.СлучайноеЧисло(0,9999999999);
            Код = Прав("0000000000" + Формат(Число,"ЧЦ=1; ЧН=0; ЧВН=; ЧГ=0"), 10);

            Результат = Массив.Найти(Код);

            Если Результат = Неопределено Тогда
                Найден = Ложь;
                Массив.Добавить(Код);
            КонецЕсли;    

        КонецЦикла; 
   
        Сообщить(Код);
    КонецЦикла;    
Показать
2. Alexey_ 27 30.12.17 17:54 Сейчас в теме
выкинь костыли и вынеси инициализацию ГСЧ за пределы цикла:
ГСЧ = Новый ГенераторСлучайныхЧисел();
Для н = 1 по 20 Цикл
	Код = "";
	Для у = 1 по 10 Цикл
		Число = ГСЧ.СлучайноеЧисло(0, 9);
		Код = Код + Формат(Число, "ЧЦ=1; ЧН=0; ЧВН=; ЧГ=0");
	КонецЦикла;
	Сообщить(Код);
КонецЦикла;
Показать
Alien_job; scarabey2006; eden_gmail; viptextil; DrAku1a; ltfriend; +6 Ответить
3. gavrilov_dv 31.12.17 01:30 Сейчас в теме
Лучше использовать соответствие. Он индексируется по умолчанию и работает быстрее (ощутите разницу на больших генерациях).
А в целом статья на статью не оч.тянет честно говоря.
4. ltfriend 31.12.17 10:01 Сейчас в теме
(3) Выше уже дали правильный ответ. Ни каких массивов, списков значений, соответствий и прочей лабуды не нужно. Нужно просто вынести инициализацию за пределы цикла.
blackijan; DrAku1a; ger_kar; +3 Ответить
5. ltfriend 31.12.17 10:09 Сейчас в теме
Подробнее, почему у автора так происходит.

Из синтаксис-помощника:
Последовательность случайных чисел для одного и того же начального числа будет одинакова.


У вас инициализация происходит прямо в цикле. За счёт того, что генерация происходит очень быстро, значение ТекущаяУниверсальнаяДатаВМиллисекундах() на следующей итерации такое же как и на предыдущей и получается та же самая последовательность псевдослучайных чисел.
А совет автора из разряда вредных.
Eskimos; DrAku1a; wolfsoft; +3 Ответить
6. DrAku1a 1792 03.01.18 16:51 Сейчас в теме
Автор, Вам уже указали в чём ошибка. Рекомендую воспользоваться информацией и описать это как "типичную ошибку новичка", или как-то так. Иначе - не вижу смысла плюсовать.
Если уж нужно проверять на отсутствие дублей - используйте соответствие, будет быстрее.
И ещё: если количество вариантов будет меньше, чем диапазон чисел (например, надо 20 вариантов целого числа от 0 до 9), то подобная процедура приведёт к зацикливанию.
7. eugeniezheludkov 45 15.01.18 01:56 Сейчас в теме
Поскольку в задаче ИНН, то он как минимум будет храниться где-то? не проще ли считать следующий на основе предыдущего?
8. scarabey2006 34 24.08.18 10:23 Сейчас в теме
2 работает норм, но нет проверки на дубли
9. Неопределено 111 24.08.18 10:31 Сейчас в теме
(8) Если включить его в цикле, со временем он перестанет выдавать случайные числа и зациклится на одинаковых.
10. Неопределено 111 27.08.18 05:48 Сейчас в теме
(8) Чтобы не быть голословным, я провёл визуальный эксперимент:
У нас есть внешняя обработка, на форме которой находится табличный документ. При открытии формы делаем ячейки квадратными с помощью
Экран.Область("R1C1:R80C80").ШиринаКолонки = 2;

и подключаем обработчик ожидания, который выдаёт координаты случайной ячейки табличного документа, а затем окрашивает её в случайный цвет. Я сделал это вот так:
&НаКлиенте
Процедура СлучайныеКоординаты()

	Х = 0;
	У = 0;
	Пока Х = 0 Цикл
		Х = СлЧисло(2)%40;
	КонецЦикла; 
	
	Пока У = 0 Цикл
		У = СлЧисло(2)%40;
	КонецЦикла;
	
	К = СлЧисло(3)%256;
	С = СлЧисло(3)%256;
	З = СлЧисло(3)%256;
	
	Экран.Область(Х, У).ЦветФона = Новый Цвет(К, С, З);
	
	ПодключитьОбработчикОжидания("СлучайныеКоординаты", 0.1, Истина);

КонецПроцедуры
 
&НаКлиенте
Функция СлЧисло(Макс)

	Для н = 1 по 20 Цикл
	    Код = "";
	    Для у = 1 по Макс Цикл
	        Число = ГСЧ.СлучайноеЧисло(0, 9);
	        Код = Код + Формат(Число, "ЧЦ=1; ЧН=0; ЧВН=; ЧГ=0");
	    КонецЦикла;
	    Возврат Число(Код);
	КонецЦикла;

КонецФункции
Показать

Я попробовал два варианта: в одном из них ГСЧ создаётся при открытии формы, а в другом в начале процедуры СлучайныеКоординаты(). Что должно получиться с табличным документом через несколько минут?

Нечто подобное. Такой результат получается если использовать стандартный ГСЧ, или тот что представлен в комментарии (2). Это получается вне зависимости от того, создаём мы генератор при открытии формы, или же каждый раз создаём его при необходимости сгенерировать случайное число. Он привязан к текущей универсальной дате, поэтому я не беспокоюсь об уникальности, ведь он вызывается не чаще 10 раз в секунду. Самое интересное происходит со временем. Вот результат стандартного ГСЧ, который создавался каждый раз при необходимости сгенерировать случайно число, он сдался быстрее всех:

Это тоже стандартный, но генератор был создан единожды при открытии формы. Он продержался дольше

Ниже представлен результат работы ГСЧ из второго комментария, который создавался каждый раз при необходимости получить случайное число. ПРодержался значительно дольше двух предыдущих

И наконец, ГСЧ из второго комментария, который был создан при открытии формы. Продержался дольше всех


Но на этом не заканчиваются фокусы. Когда ломается генератор, ломается интерфейс. Не только платформы, но и винды (во всяком случае семёрки):

1. Слетают шрифты в панели с подсистемами. Картинки в ней исчезают.
2. В открытой обработке появились кнопки из открытого документа, причём кривые.
3. В то время как открыта обработка, активна вкладка документа, но работать мы можем с обработкой.
4. Ломается кнопка "Пуск".

Интересно, почему всё серое? Диапазон цветов состоит из трёх значений, каждое из которых может быть равно числу от 0 до 255, т.е. всего 256 значений. Серый цвет -- это самый усреднённый цвет. Его значение равно 128, 128, 128 (3 раза 256/2). Единственное чего я не понимаю так это почему он стабильно выдаёт среднее значение от 0 до 255, но закрашивает клетки не по диагонали, или не в одном месте.
Для отправки сообщения требуется регистрация/авторизация