Поскольку вас больше всего интересует длина прогона, вы можете генерировать случайные длины прогонов вместо случайных битов, чтобы дать им точное распределение, которое вы хотите.
Средняя длина прогона в случайных двоичных данных, конечно, равна 4 (сумма n / (2 ^ (n-1))), а средняя в режиме 1. Вот некоторые случайные биты (клянусь, это один прогон Я не выбрал значение, чтобы высказать свою точку зрения):
0111111011111110110001000101111001100000000111001010101101001000
Видите, там длина пробега 8. Это не особенно удивительно, поскольку длина прогона 8 должна происходить примерно каждые 256 бит, а я сгенерировал 64 бита.
Если это не выглядит «случайным» для вас из-за чрезмерной длины прогона, то генерируйте длины прогона с любым желаемым распределением. В псевдокоде:
loop
get a random number
output that many 1 bits
get a random number
output that many 0 bits
endloop
Возможно, вы захотите отбросить некоторые исходные данные из потока или рандомизировать первый бит, чтобы избежать проблемы, заключающейся в том, что первый бит всегда равен 1. Вероятность того, что N-й бит равен 1, зависит от того, как вы «получаете случайное число», но для всего, что достигает «коротких, но не слишком коротких» длин пробега, оно скоро будет настолько близко к 50%, что не имеет значения.
Например, «получить случайное число» может сделать это:
get a uniformly-distributed random number n from 1 to 81
if n is between 1 and 54, return 1
if n is between 55 and 72, return 2
if n is between 72 and 78, return 3
if n is between 79 and 80, return 4
return 5
Идея состоит в том, что вероятность прогона длины N равна одной трети вероятности прогона длины N-1, а не половине. Это даст намного меньшую среднюю длину пробега и самый длинный пробел из 5, и, следовательно, будет выглядеть «более случайным» для вас. Конечно, это не «выглядело бы случайным» для любого, кто привык иметь дело с последовательностями бросков монет, потому что они думали, что пробеги были слишком короткими. Вы также можете очень легко сказать с помощью статистических тестов, что значение цифры N коррелирует со значением цифры N-1.
Этот код использует как минимум log (81) = 6,34 "случайных битов" для генерации в среднем 1,44 битов вывода, поэтому он медленнее, чем просто генерация битов с равномерным распределением. Но это не должно быть намного больше, чем примерно в 7 / 1,44 = 5 раз медленнее, и LFSR довольно быстро начать с.