Здравствуйте, subdmitry, Вы писали:
S>В принципе такого эффекта несложно достичь, применив к последовательности от 0 до 2**48-1 обратимую функцию, дающую хорошее перемешивание (в криптографическом смысле этого слова). Тут уже предложили взять какой-нибудь блочный шифр. Это в общем-то правильная идея, только это а) сложно б) еще надо найти блочный шифр с блоком в 48 бит.
Но можно сделать и проще. Я бы предложил такой вариант.
S>S>typedef unsigned __int64 u64;
S>u64 seed=0;
S>u64 GetNextNumber() {
S> u64 v= seed++;
S> for (int i=0; i<4; i++)
S> v = ((v^(v>>40)) * 0xA9C839464437) & (1<<48)-1;
S> return v;
S>}
S>
S>Идея тут такая, что умножение хорошо подмешивает младшие биты к старшим, а сдвиг вправо подмешивает старшие биты к младшим. Число взято от балды, важно только, что оно нечетное. Поскольку все операции обратимы, получаемая последовательность должна быть перестановкой чисел от 0 до 2**48-1.
Кто сказал, что они обратимые? Операция & в конце обратимая? Где гарантия, что два числа не дадут один и тот же результат по модулю (1<<48)-1 после умножения?
Если даже это так, то насколько взятое наугад число дает хорошие характеристики получаемой случайной последовательности?