В компиляторе есть стандартный генератор:
int rand(void)- returns a pseudo random number between 0 and RAND_MAX.
Только насчет равномерности они лукавят.
Во времена Спектрумов и БК можно было легко проверить равномерность - 1-е случайное число подаем на X, 2-е на Y, 3-е на COLOR и рисуем на экране точки.
Так вот, эти точки ложатся вблизи диагонали экрана.
Меня не устраивали ни их равномерность, ни использование плавучей арифметики. Нужен был компактный и быстрый код.
Вот моторольный ассемблер: (b=R3 - 2байта вход и выход)
MOV #5,R0 ; цикл до 5
$1: MOV R3,R2 ; c = b
ROL R3 ; b = b ‹‹ 1
ADD R3,R2 ; c = c + b
INC R3 ; b = b + 1
XOR R2,R3 ; b = b ^ c
ASL R3 ; b = b ‹‹ 1
ADD R2,R3 ; b = b + c
ADD #771,R3 ; b = b + 771
SWAB R3 ; поменять местами байты
SOB R0,$1 ; повторить еще 4 раза
; выход (результат в R3)
Вот на Модуле:
PROCEDURE RND(b:INTEGER):INTEGER;
VAR
c,d : INTEGER;
BEGIN
FOR d:=1 TO 5 DO
c := b; b := b * 2; c := c + b;
b := ( INTEGER(BITSET(b + 1) / BITSET(c)) ‹‹ 1 ) + c + 303H;
b := (b ‹‹
![Горд собой](images/smilies/icon_dovl.gif)
+ (b ››
![Горд собой](images/smilies/icon_dovl.gif)
;
END;
RETURN b;
END RND;
Я сейчас попытаюсь портировать с Модулы на C:
int RND(int b) {
int c,d;
for (d=1;d‹=5;d++) {
c = b; b = b ‹‹ 1; c = c + b;
b = ((b + 1) ^ c) ‹‹ 1 ) + c + 0x0303;
b = (b ‹‹
![Горд собой](images/smilies/icon_dovl.gif)
+ (b ››
![Горд собой](images/smilies/icon_dovl.gif)
;
}
return b;
}
1-й вызов - с базовым значением последовательности (можно использовать в кач-ве пароля при кодировании данных этим генератором):
..
r = RND(100);
последующие вызовы - обязательно подставлять предыдущий результат:
r = RND(r);