Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Алгоритмы > Про RND |
Автор: serious 19.3.2003, 04:51 |
Как можно предсказать генератор случайных чисел, возможно ли это? А обратно можно, т.е. на основании полученных данных найти исходные? |
Автор: Paradox 19.3.2003, 14:25 |
На основе борльшой совокупности статистических данных предсказать можно, т.к. все эти числа все равно псевдослучайные и в конце концов начинают повторятся (возможно с очень длинным периодом). Об этом еще Кнут писал ![]() |
Автор: Alex101 19.3.2003, 18:09 |
Так он и есть псевдослучайный - при большом количестве данных количество нулевых битов равняется единичным. |
Автор: Chingachguk 19.3.2003, 18:09 |
Если известен вид генератора с точностью до коэффициентов, то можно (например, перебором). |
Автор: neutrino 19.3.2003, 19:00 |
Skajem tak, pereborom mojno v ljubom sluchae, t.k. period psevdosluchai'noi' posledovatel'nosti v komp'jutere ogranichen. Tol'ko esli znat' raspredelenie, kotoromu podchinjaetsja posledovatel'nost', to nai'ti chisla budet namnogo legche. Exhe ochen' pomoglo by, esli ty znal chast' posledovatel'nosti, kotoraja uje pojavilas' i metod generacii chisel. |
Автор: neutrino 19.3.2003, 19:11 |
Che-to ja prognal. Esli ty znaesh' metod i chislo posledovatel'nosti vmeste s ego indeksom, to mojno so-100% garantiei' ukazat' sledujuxhii' chlen posledovatelnosti. |
Автор: podval 20.3.2003, 01:44 |
Если ПСП формируется линейным рекуррентным регистром, то можно, если удастся за обозримое время решить большую систему уравнений. |
Автор: Step 20.3.2003, 02:12 | ||||
|
Автор: val 20.3.2003, 02:21 |
Не существует генераторов чисто случайных чисел, поведение которых не подчиняется конкретному закону генерирования случайной последовательности… Поэтому теоретически возможно предсказание работы генератора как по входу так и по выходу… |
Автор: Step 20.3.2003, 02:24 | ||
|
Автор: serious 20.3.2003, 03:30 |
Расскажите устройство стандартного random() |
Автор: maxim1000 20.3.2003, 04:07 |
насколько мне известно, стандартный random() реализован так: x(n+1)=a*x(n)+b mod m |
Автор: Step 20.3.2003, 04:25 | ||
|
Автор: maxim1000 20.3.2003, 05:18 | ||||
вообще я слышал, что его уже на что-то заменили, но точно знаю, что некоторое время назад он был и в Pascale, и в C.
что такое двоичное гаммирование, не знаю а регистр сдвига вот: (это нам так рассказывали на криптологии) x(n+1)=f(x(n),x(n-1),x(n-2),...,x(n-k)) соответственно линейный регистр сдвига (он же линейный рекуррентный регистр сдвига) - когда функция f линейна все операции делаются по модулю m (а m часто берут 2^n) |
Автор: Chingachguk 20.3.2003, 17:32 | ||||
И в BC3.1, и в TP7.0, и в VC6++, и Linux (соответсвенно, в perl, си, си++ под линух).
Отчего плохой ? Для алгоритма скринсейвера неплохой ? А для чего тогда плохой ? |
Автор: Step 20.3.2003, 18:32 | ||
|
Автор: neutrino 20.3.2003, 19:43 |
Kak raz, ochen' daje ravnoverojatnoe. U Knuta v pervom tome jetot additivnyi' sposob byl razjevan. Vot kak iz jetogo raspredelenija poluchit' drugoe - jeto vopros. Pravda summa jetih ravnoverojatnyh znachenii' daet priblijennoe normal'noe raspredelenie. |
Автор: Step 20.3.2003, 19:57 | ||
|
Автор: neutrino 20.3.2003, 22:00 | ||||
Vot proga:
A eto ee vyvod:
Nu kak, ravnoverojatno? |
Автор: Step 20.3.2003, 23:19 | ||||
двоичное гомирование дает более лучший результат |
Автор: neutrino 21.3.2003, 00:40 | ||||
Privedi primer. Tak jeto ja tol'ko 50x20 opytov proizvel, a esli 5000x100, to:
Kak vidno dispersija men'she (otnositel'naja) |
Автор: Step 21.3.2003, 00:44 | ||
|
Автор: maxim1000 21.3.2003, 02:58 |
для скринсейвера алгоритм действительно неплохой а вот, когда его начинают использовать для серьезных задач, проявляются его неприятные свойства если смотреть распределение единичного случайного числа, то оно действительно очень близко к равномерному (как и показали приведенные здесь экспериментальные данные) такие же результаты можно получить, если использовать такой вот алгоритм: x(n+1)=x(n)+1 mod m все дело в распределении вектора, состоящего из нескольких последовательно полученных значений если генератор хороший, то они должны равномерно заполнять гиперкуб (ну с поправкой |
Автор: maxim1000 21.3.2003, 03:03 |
прошу прощения, произошел несчастный случай - я случайно нажал на кнопку "отправить"... так вот, этот реализации этого вектора должны заполнять этот куб равномерно. вектор из двух значений будет удовлетворять одному и тому же линейному уравнению, которое и задает его работу получается, что реализации вектора будут лежать на одной гиперплоскости, а значит, не заполнят куб равномерно. если с помощью такого генератора выбирать ключи для какого-нибудь шифрования, можно сильно облегчить работу тем, кто ее будет взламывать... |
Автор: Step 21.3.2003, 03:05 | ||
|
Автор: maxim1000 21.3.2003, 03:29 |
не больше m ![]() например, если a=1, b=1 - период максимален |
Автор: neutrino 21.3.2003, 03:57 | ||
...Donald Knuth, vol.1 |
Автор: podval 21.3.2003, 05:20 | ||
Позвольте поправить. Правильно так: ГАММИРОВАНИЕ, от слова ГАММА. |
Автор: podval 21.3.2003, 05:30 |
О линейном рекуррентном регистре (очень полезно почитать) http://pitis.tsure.ru/files12/09.pdf |
Автор: Step 21.3.2003, 18:57 | ||
|
Автор: stab 22.3.2003, 01:51 |
Вот реализация Random(int) в Delphi 6: считаем что символ PIC НЕопределен, на сколько я понял это под Kylix (GOT - global offset table, вроде это понятие из области unix-подобных систем) {$IFDEF PIC} function GetGOT: LongWord; export; begin asm MOV Result,EBX end; end; {$ENDIF} procedure _RandInt; asm { ->EAX Range } { <-EAX Result } PUSH EBX {$IFDEF PIC} PUSH EAX CALL GetGOT MOV EBX,EAX POP EAX MOV ECX,[EBX].OFFSET RandSeed IMUL EDX,[ECX],08088405H INC EDX MOV [ECX],EDX {$ELSE} // обнуляем EBX, зачем ![]() XOR EBX, EBX // перемножаем RandSeed и 134775813 (08088405H) IMUL EDX,[EBX].RandSeed,08088405H // увеличиваем на еденицу старшее двойное слово результата умножения INC EDX // сохраняем старшее двойное слово результата умножения как новый RandSeed MOV [EBX].RandSeed,EDX {$ENDIF} // умножаем преданный в качестве параметра диапазон на старшее двойное слово предыдущего результата MUL EDX // берем старшее двойное слово от предыдущего умножения, это и будет результат MOV EAX,EDX POP EBX end; знающие люди напишите формулу ![]() у мя не выходит, не дружен я с математикой ![]() |
Автор: maxim1000 22.3.2003, 02:44 | ||||
часто в качестве m берут что-то вроде 2^32 по-моему, это совсем неплохо для периода
это был бы в точности тот алгоритм, который и предполагается, если последние две операции выполнялись не над старшим dword, а над младшим. в этом случае a=134775813, b=1, m=2^32 если все же операции выполнять над старшим словом, может получиться такая наприятная ситуация: пусть RandSeed=1 (должно же такое бывать) тогда 134775813*RandSeed=134775813 старшее dword результата произведения равно 0 тогда RandSeed=1 к сожалению, я не знаю этого ассемблера и ориентируюсь только по комментариям... |
Автор: stab 22.3.2003, 03:43 |
хм, я не много ошибся в разборе поцедуры. После первого умножения идет работа с младшим двойным словом. Вот верный вариант: procedure _RandInt; asm { ->EAX Range } { <-EAX Result } PUSH EBX {$IFDEF PIC} PUSH EAX CALL GetGOT MOV EBX,EAX POP EAX MOV ECX,[EBX].OFFSET RandSeed IMUL EDX,[ECX],08088405H INC EDX MOV [ECX],EDX {$ELSE} // обнуляем EBX, зачем , можно просто IMUL EDX,[RandSeed],08088405H XOR EBX, EBX // перемножаем RandSeed и 134775813 (08088405H) IMUL EDX,[EBX].RandSeed,08088405H // увеличиваем на еденицу младшее двойное слово результата умножения INC EDX // сохраняем младшее двойное слово результата умножения как новый RandSeed MOV [EBX].RandSeed,EDX {$ENDIF} // умножаем преданный в качестве параметра диапазон на младшее двойное слово предыдущего результата MUL EDX // берем старшее двойное слово от предыдущего умножения, это и будет результат MOV EAX,EDX POP EBX end; |
Автор: stab 22.3.2003, 03:51 |
и еще вопрос в догонку: чем обоснован выбор a=134775813? |
Автор: maxim1000 22.3.2003, 05:31 |
От этого числа (в большей степени, чем от b) зависит равномерность распределения выходных значений. Если немного попреобразовывать эту формулу, можно прийти к линейному регистру сдвига: x(n)=a*x(n-1)+b x(n+1)=a*x(n)+b b=x(n)-a*x(n-1) x(n+1)=a*x(n)+x(n)-a*x(n-1) ----------------------------------- x(n+1)=(a+1)*x(n)-a*x(n-1) [надеюсь я ничего не напутал ![]() (только теперь надо задавать два начальных значения) Линейные регистры сдвига довольно хорошо изучены. Известны зависимости некоторых показателей качества генерируемых ними последовательностей от коэффициентов линейного рагистра. Нам в институте дали только способ определения периода с помощью характеристических полиномов регистра, а показателей качества псевдослучайных последовательностей дали около десятка. Думаю, обоснование выбора подобных чисел можно найти в книгах по криптологии или связанным с ней дисциплинам... P.S. А первое, что приходит в голову - a не должно быть делителем m (в нашем случае оно просто должно быть нечетным), но это - лишь первый шаг для сужения области поиска подходящих чисел |
Автор: stab 23.3.2003, 10:33 |
ок, все понятно, но вернемся к вопросу топика ![]() есть у меня большая выборка значений (100 000) и что делать дальше? как построить гипотезу о вожмоном устройстве датчика? ... и предсказать следуещее 100 001 значение ? ![]() |
Автор: maxim1000 23.3.2003, 23:05 | ||||||||
наконец-то проделал несколько экспериментов вот некоторые результаты: У генератора x(n+1)=a*x(n)+b есть неприятная особенность: на каждом шаге меняется четность. (это если "a" нечетное, иначе четность вообще меняться не будет)
Боюсь, что это не так. В BC++3.1 и в VC++6.0 генератор случайных чисел построен по-другому (к сожалению, не знаю как) Этот генератор я обнаружил только в Delphi (наверное, он есть и в TP7.0, но я не проверял) В C++ генератор другой, он не обладает вышеописанным свойством
Для предсказания этого генератора нужно не больше трех последовательных чисел: 1, если известны a,b 2, если известно что-то одно 3, если оба коэффициента неизвестны А вот, собственно, алгоритм предсказания: x(n+1)=a*x(n)+b mod m ![]() m=2^32 a=134775813 b=1 Возможны случаи, когда мы работаем с генератором, у которого другие коэффициенты: тогда составляем систему уравнений, использующих несколько последовательных значений из этой системы находим коэффициенты
Скорее всего, нужно перебирать все известные гипотезы, пока одна не подойдет. Состояние рассмотренного генератора полностью описывается его выходом (RandSeed) Состояние любого реккурентного регистра полностью описывается несколькими последними выходами Но ведь можно построить генератор, состояние которого будет скрыто, а за выход будет браться какая-то функция от состояния такой генератор значительно сложнее взломать. А еще достаточно добавить подходящую нелинейность, чтобы практически обезвредить весь линейный анализ.
Конечно, если есть все данные за период, можно с легкостью предсказать каждое следующее значение. Однако, почти всегда период измеряется величинами порядка 2^32. Вообще предсказание генераторов случайных чисел часто используется при взломе шифров, поэтому этих генераторов уже понапридумывали кучу, и характеристики у них значительно лучше, чем стандартных. P.S. извините за большой размер сообщения, оно все как-то само получилось |
Автор: neutrino 24.3.2003, 00:38 | ||
2maxim1000:Угу, именно этот способ я и имел в виду в начале дискуссии.
По-моему здесь имелся в виду статистический анализ. |
Автор: Chingachguk 24.3.2003, 19:43 | ||||||
srand от VC6++:
rand() от VC6++:
Другими словами, в VC6++ алгоритм у rand() такой: seed' = ( seed * 0x343FD (знаковое умножение) + 0x269EC3 ) mod 2^32; результат от ф-ции rand будет: rand() = (seed' >> 16) & 7FFFh; Если не веришь, задай конкретные значения в srand'е (0,1 ...) и проверь ;) |
Автор: neutrino 24.3.2003, 20:08 | ||
Тут пришел Chingachguk и все опошлил ![]()
шутка? Kstati, pro integral - ja ego privel k vidu gamma funkcii i poluchilos', chto ot 0 do +infinity budet 2 (=2*г(1)=2*0!=2) |
Автор: Chingachguk 24.3.2003, 22:22 | ||||
Почему ? mov eax,[holdrand (00423a50)] // eax = seed' sar eax,10h // eax >> = 16 and eax,7FFFh // eax & = 0x7FFFh Так что безо всяких шуток. И в BC3.1 то же самое. Проверь так: max=0; for (i=0;i<10000;i++) { randval= rand(); if max<randval max=randval; } printf("MaxRand=%u",randval); А вот в linux совсем иначе: чаще всего процедуры типа drand/srand компилируются с дефайном MAX_BITS 48.
Так то ж ... аналитически. И зачем gamma, если такая простая подинтегральная (exp(-const*t)) ? |
Автор: remax 20.4.2003, 18:44 |
Кстати, а какие способы оценки качества псевдослучайных последовательностей существуют? Как, например, определить скоррелированность между последовательными значениями случайной величины? Почему то обычно оценивают взаимосвязь между различными случайными величинами (парная корреляция). Хотя, очевидно что при характеризации случайной величины важен не только вид функции распределения (равномерное, нормальное ....) но и сгруппированость значений внутри последовательности. |
Автор: Chingachguk 21.4.2003, 08:48 | ||
Например, автокорреляционная функция:
Но это специфическая реализация (моя) для конкретного дела, так что лучше смотреть sources ;) |
Автор: stab 21.4.2003, 16:13 |
а как быть с "Алгоритм Л'Экюера, комбинирующий две последовательности" ? http://algolist.manual.ru/maths/generator/lequer.php |