Генератор случайных чисел
© Darky & Serge Sh. Damage Inc, г. Нижний Новгород, 1994.
Мы решили поделиться крайне полезной, на наш взгляд, процедурой. Не секрет, что в программах, требующих многократных вызовов генератора случайных чисел, на это затрачивается львиная доля времени. Как правило, чтобы не изобретать велосипед, большинство программистов используют встроенную функцию ПЗУ, которая работает крайне медленно вследствие активного использования встроенного калькулятора. Мы также не считаем себя изобретателями велосипедов и решили просто "облегчить конструкцию".
Немного теории. Функция ПЗУ генерирует случайное число по следующей формуле: SEED=(((SEED+1)*75) MOD 65537)-1,
где SEED - это системная переменная Бейсика (23670/23671). Каждый раз при обращении к функции RND в нее заносится очередное, полученное по этой формуле, число. Сама же функция RND возвращает в Бейсик значение SEED/65536, что и дает число в диапазоне [0,1]. Посмотрим на числа, образующие формулу SEED: 1; 75, 65537. где здесь плавающая точка?!! Зачем здесь встроенный калькулятор? Об работку трехбайтовых чисел можно реализовать и на Ассемблере. Мы хотим предложить Вам вариант вычисления случайного числа по тому же алгоритму без использования "плавающей" арифметики (и калькулятора!).
Итак, процедура RND.
00010 |
ORG |
40000 |
|
00020 |
ENT |
|
|
00030 |
LD |
HL,(SEED) |
|
00040 |
INC |
HL |
|
00050 |
LD |
D,0 |
;Инкремент трехбайтового |
00060 |
LD |
A, H |
;числа, которое образуют |
00070 |
OR |
L |
;регистры D, H, L |
00080 |
JR |
NZ,NOCARRY ; |
00090 |
INC |
D |
|
00100 NOCARRY |
PUSH |
DE |
;Сохранили новый SEED |
00110 |
PUSH |
HL |
|
00120 |
SLA |
L |
|
00130 |
RL |
H |
|
00140 |
RL |
D |
;Умножили на 2 |
00150 |
PUSH |
DE |
;-Сохранили SEED*2 |
00160 |
PUSH |
HL |
|
00170 |
SLA |
L |
|
00180 |
RL |
H |
|
00190 |
RL |
D |
; Умножили на 4 |
00200 |
SLA |
L |
|
00210 |
RL |
H |
|
00220 |
RL |
D |
; Умножили на 8 |
00230 |
PUSH |
DE |
;Сохранили SEED*8 |
00240 |
PUSH |
HL |
|
00250 |
SLA |
L |
|
00260 |
RL |
H |
|
00270 |
RL |
D |
; Умножили на 16 |
00280 |
SLA |
L |
|
00290 |
RL |
H |
|
00300 |
RL |
D |
; Умножили на 32 |
00310 |
SLA |
L |
|
00320 |
RL |
H |
|
00330 |
RL |
D |
; Умножили на 64 |
00340 |
POP |
BC |
|
00350 |
POP |
AF |
|
00360 |
ADD |
HL, BC |
|
00370 |
ADC |
A, D |
|
00380 |
LD |
D,A |
;SEED*64+SEED*8 |
00390 |
POP |
BC |
|
00400 |
POP |
AF |
|
00410 |
ADD |
HL, BC |
|
00420 |
ADC |
A, D |
|
00430 |
LD |
D,A |
;SEED*64+SEED*8+SEED*2 |
00440 |
POP |
BC |
|
00450 |
POP |
AF |
|
00460 |
ADD |
HL, BC |
00470 |
ADC |
A, D |
; то есть SEED*75 |
|
|
00480 |
LD |
C,A |
00490 |
LD |
B, 0 |
00500 |
OR |
A |
00510 |
SBC |
HL, BC |
00520 |
ADC |
HL, BC |
00530 |
OR |
A |
00540 |
SBC |
HL, BC |
00550 |
DEC |
HL |
00560 |
LD |
(SEED) |
00570 |
RET |
|
00580 SEED |
DEFW |
0 |
Start of object: |
# 9C4 0 |
(40000) |
Length: |
#0055 |
(00085) |
Executes: |
# 9C4 0 |
(40000) |
HL
■ SEED*64 + SEED*8 + SEED*2 + SEED
Подпрограмма возвращает в регистр HL (и в пару ячеек SEED) псевдослучайное число в диапазоне [0,65535]. Делайте с ним, что хотите.
Мы пожертвовали объемом ради скорости работы, поэтому однотипные участки текста не были выделены в отдельные подпрограммы.
Шестнадцатеричный дамп процедура RND:
9C4 0 |
2A |
93 |
9C |
23 |
16 |
00 |
7C |
B5 |
9F |
9C4 8 |
20 |
01 |
14 |
D5 |
E5 |
CB |
25 |
CB |
8E |
9C50 |
14 |
CB |
12 |
D5 |
E5 |
CB |
25 |
CB |
52 |
9C58 |
14 |
CB |
12 |
CB |
25 |
CB |
14 |
CB |
7F |
9C60 |
12 |
D5 |
E5 |
CB |
25 |
CB |
14 |
CB |
62 |
9C68 |
12 |
CB |
25 |
CB |
14 |
CB |
12 |
CB |
8D |
9C7 0 |
25 |
CB |
14 |
CB |
12 |
C1 |
F1 |
09 |
A8 |
9C7 8 |
8A |
57 |
C1 |
F1 |
09 |
8A |
57 |
C1 |
52 |
9C80 |
F1 |
09 |
8A |
4F |
06 |
00 |
B7 |
ED |
99 |
9C88 |
42 |
ED |
4A |
B7 |
ED |
42 |
2B |
22 |
D0 |
9C90 |
93 |
9C |
C9 |
00 |
00 |
00 |
00 |
00 |
24 |
Мы вставили этот генератор в свои программы ("Минер", "Пасьянс") и результат нас поразил! Пришлось убирать из программ все надписи типа: "Please, wait.", так как их все равно никто не успел бы разглядеть. Будем надеяться, что наша работа кому-то поможет.
Безусловно, поможет. Мыг в этом уверены. Да вот, посмотрите, хотя был, следующую статью...