Вход

Просмотр полной версии : Генератор псевдослучайных чисел



Alex/AT
31.03.2014, 16:08
Не знаю, может где-то уже что-то подобное пробегало, может кому-то пригодится.

Быстрый (116T) генератор псевдослучайных чисел на основе LCG с неплохой равномерностью:


Random8
; breaks A,HL,DE, returns pseudo-random u8 value in A
; consumes 116T including RET

; ALGO: u16 seed = (seed << 7) - seed + 251
; ALGO: result = (u8) (seed + seed >> 8)

LD HL,#55AA ; 10T, 10T
.seed EQU $-2 ; initialize Random8+1 (seed) with different u16 values to get different sequences
LD E,L ; 4T, 14T
LD D,H ; 4T, 18T
XOR A ; 4T, 22T
SRL H ; 8T, 30T
RR L ; 8T, 38T
RRA ; 4T, 42T
LD H,L ; 4T, 46T
LD L,A ; 4T, 50T
SBC HL,DE ; 11T, 61T
LD DE,251 ; 10T, 71T
ADD HL,DE ; 11T, 82T
LD (.seed),HL ; 16T, 98T
LD A,L ; 4T, 102T
ADD A,H ; 4T, 106T
RET ; 10T, 116T

zebest
31.03.2014, 17:28
я так понимаю это генератор от 0 до 255?
Как его переделать oт 0 до 7 ?
резальт в аккумуляторе поделить на 32? сдвигом можно сделать?)

Andrew771
31.03.2014, 17:52
and %00000111

ram_scan
02.04.2014, 07:28
Каноничный генератор. 16-битный. Полином из умной книжки. Длина последовательности 65535. Тактов когда писал не считал, поленился. может статься что он быстрее вышеприведенного. Использовался мною для написания тестрома в части теста ОЗУ.


;-------------------------------------------------------------------------------
; Генератор псевдослучайных чисел на сдвиговом регистре.
; Полином [1,2,4,15] (период 65535)
; Входные параметры: HL - SEED
; Выходные параметры: HL - новый SEED
; Модифицирует: HL, AF, E
;-------------------------------------------------------------------------------
MACRO RANDOM
ld a,h
rlca ; бит 15 положили в бит 0 аккумулятора
ld e,l ; запомнили младшие биты
add hl,hl ; сдвинули регистр на бит влево
srl e ; в бит 0 регистра e положили бит 1 SEED
xor e ; поксорили с 15 битом
srl e ; в бит 0 регистра e положили 2 бит SEED
xor e ; поксорили с результатом
srl e ; пропускаем бит 3
srl e ; в 0 бит вдвигаем 4 бит SEED
xor e ; поксорили с результатом
and %00000001 ; выделили младший бит
xor l
ld l,a
ENDM


UPD: проверил первый генератор. Работает отвратительно. Не рекомендую.

Titus
02.04.2014, 07:59
UPD: проверил первый генератор. Работает отвратительно. Не рекомендую.

Как ты его проверял?

ram_scan
02.04.2014, 08:05
Как ты его проверял?

Заполнил несколько раз подряд видеопамять (умозрительно он выходил на десяток тактов прытче моего, хотел под свой тест памяти его приладить). Генератор быстро вырождается и на экране устанавливается статичная картинка с характерными вертикальными полосами. Кроме того видно регулярные повторяющиеся паттерны.

Выкинул.

Могу приложить скриншоты, если на слово не верите.

introspec
02.04.2014, 09:16
Вот генератор из коллекции Baze (http://baze.au.com/misc/z80bits.html), он тоже чуть медленнее. Визуально по распределению точек я его не проверял, но скорость у него адекватная и проблем с качеством полученных случайных чисел я с ним не видел.
This generator was taken from an old ZX Spectrum game and slightly optimised.

Input: none
Output: HL = pseudo-random number, period 65536

Rand16 ld de,Seed ; Seed is usually 0
ld a,d
ld h,e
ld l,253
or a
sbc hl,de
sbc a,0
sbc hl,de
ld d,0
sbc a,d
ld e,a
sbc hl,de
jr nc,Rand
inc hl
Rand ld (Rand16+1),hl
ret

jerri
02.04.2014, 09:27
Переписанный генератор из ПЗУ бейсика


random
ld de,0
seed equ $-2
xor a
ld h,a,l,a,b,a
add hl,de
adc a,b
add hl,hl
adc a,a
add hl,hl
adc a,a
add hl,hl
adc a,a
add hl,de
adc a,b
add hl,hl
adc a,a
add hl,hl
adc a,a
add hl,de
adc a,b
add hl,hl
adc a,a
add hl,de
adc a,b
sub #4a
neg
ld c,a
add hl,bc
ld (seed),hl
ret

формулу не помню, но генерит идеально

denpopov
02.04.2014, 10:26
юзал другой, мне хватило..


random:
R1:LD C,$15+3
R2:LD A,#70
ADD A,C:LD C,A
LD (R1+1),A
R3:LD A,#FD
SUB C:LD C,A,(R2+1),A
RRCA:LD (R3+1),A
LD A,C

ram_scan
02.04.2014, 12:02
Вот генератор из коллекции Baze (http://baze.au.com/misc/z80bits.html), он тоже чуть медленнее.

Проверил его, вельми хороший генератор. Его рекомендовать можно. Правда он как мне кажется чуть тормознее моего варианта, надо такты посчитать.

Shadow Maker
02.04.2014, 12:06
Программу (сурсы?) для тестов в студию.

Titus
02.04.2014, 12:08
Заполнил несколько раз подряд видеопамять

Я тоже так проверяю)))

Делал когда-то свой генератор случайных чисел на Амиге (для эмулятора Денди, шумового канала), и тоже так на экране его проверял. Менял алгоритм, пока распределение на экране не стало выглядеть случайным. Вот этот амижный код в Сишном эквиваленте:


UINT8 FastRND(void)
{
static UINT16 D2 = 42286,
D1 = 65535,
A1 = 30609,
D3;

D3 = D1 + A1;
A1 = D1 ^ 0xFFFF;
D1 = (D2 >> 5) | (D2 << 11);
D2 = D2 + D3;

return D2;
}

Shadow Maker
02.04.2014, 12:24
Я не уверен, что ram_scan так проверяет. Вот и уточняю.

introspec
02.04.2014, 12:33
Проверил его, вельми хороший генератор. Его рекомендовать можно. Правда он как мне кажется чуть тормознее моего варианта, надо такты посчитать.
Я прикинул сейчас в уме, разница в десяток тактов, не больше. Вообще, нужно будет найти список полиномов и выбрать такой, чтоб попроще кодился...

Sent from my HTC Sensation XE with Beats Audio Z715e using Tapatalk

psb
02.04.2014, 12:51
and %00000111
плохой способ для LCG.

alone
02.04.2014, 16:23
RND-генератор с ОЧЕНЬ большим периодом:



II. Основанный на LFSR
генератор случайных байт

Как написано в умных книжках [4], один
из таких генераторов придуман Mitchell'ом
и Moore'ом и имеет вид:


X[n] = ( X[n-24] + X[n-55] ) mod m

Если m=2^k, то период такого генератора
(2^55-1)·2^(k-1), что для случая байтов
составит 2^(55-1)·2^7 ў 2^62 ў 4.6·10^18.

Можно заметить, что для младшего бита
такой генератор представляет собой LFSR-
генератор (в данном случае N=55, K=24 ).
Можно было бы вместо сложения использовать
операцию XOR, в этом случае мы имели бы 8
55-битовых LFSR, генерирующих различные
фазы последовательности длиной 2^55-1 бит
и комбинируемые в 1 байт. Вместо LFSR с
параметрами N=55, K=24 можно использовать
любой другой с последовательностью макси─
мальной длины.

Реализация на Z80 (с таблицей 256 байт):

DO_RND
;OUT: A или B или C - случайный байт


LD H,'PRT_RND ; 256-байтовая
;таблица
CURND LD A,0
INC A
LD (CURND+1),A ; не случайный
;номер, а лишь
;указатель в таблице
LD L,A
LD B,(HL)
ADD A,55-24
LD L,A
LD C,(HL)
ADD A,24
LD L,A
LD A,B
ADD A,C
LD (HL),A
;в регистрах A, B и С находятся случайные
;величины, отстоящие друг от друга на
;несколько десятков отсчётов
RET

Перед использованием такого генератора
следует записать хотя бы 1 ненулевой байт
в таблицу PRT_RND, а чтобы случайные числа
получались хорошими сразу - лучше запол─
нить таблицу каким-нибудь данными с более-
менее равномерным распределением всех
байт.


http://zxpress.ru/article.php?id=8675

ram_scan
02.04.2014, 17:56
Я прикинул сейчас в уме, разница в десяток тактов, не больше. Вообще, нужно будет найти список полиномов и выбрать такой, чтоб попроще кодился...

Для сдвигового 16-битного регистра с обратной связью такой полином только один, который я и использовал. Можно конечно генератор перекодить, если с неочевидным битовым трюкачеством быстро суметь четность посчитать (под четностью понимается четное/нечетное количество единичных битов в слове). Я литературу проштудировал на этот счет, но мне показалось все-таки в лоб проще сделать, не хватает "аккумуляторов" на Z80 для того чтобы изящно сделать. На писюке четность с битовыми трюками считается быстро и изящно. Но там и классический генератор любой разрядности с делением закодить несложно, либо сопроцессор за вымя потрогать.

Для 32 бит есть других полиномов, они собсно все в литературе описаны.

zebest
02.04.2014, 22:46
http://www.worldofspectrum.org/forums/showthread.php?t=39632
и там же еще ссылка. У поляков тоже тема есть давно, и с примерами..

introspec
04.04.2014, 09:57
Для сдвигового 16-битного регистра с обратной связью такой полином только один, который я и использовал.
Вот тут лежат коэффициенты всех 2048 возможных линейных сдвиговых генераторов с полным периодом: http://www.ece.cmu.edu/~koopman/lfsr/index.html

Не все они могут оказаться "хорошими", потому что степень "замешивания" битов не проверяется. Тем не менее, наверняка, в этом списке найдутся достойные альтернативы вашему варианту.

denpopov
04.04.2014, 10:13
А если построить огибающий колокол?
http://www.cognitivist.ru/kernel/prologi/prologi_388.png

Titus
04.04.2014, 11:17
А если построить огибающий колокол?

Алгоритм? Что за сумма величин?

introspec
06.04.2014, 19:33
Вот очень быстрый генератор ПСЧ на основе LSFR по схеме Галуа:
Galois16: ld hl, #FFFF ; 10
SeedValue: EQU $-2
add hl, hl ; 11
sbc a ; 4
and #BD ; 7 instead of #BD, one can use #2D, #39, #3F, #53 or #D7
xor l ; 4
ld l, a ; 4
ld (SeedValue), hl ; 16
ret ; 10
Всего 66 тактов. С любым из перечисленных значений константы обратной связи, этот генератор даёт период в 65535 значений. Внимание: использовать 0 в качестве затравочной константы нельзя.

Barmaley_m
06.04.2014, 21:17
этот генератор даёт период в 65535 значений
LFSR дает хорошие случайные биты, но вот использовать все биты состояния в качестве 8- или 16-разрядных случайных чисел не рекомендуется: они все-таки довольно сильно коррелируют между соседними раундами работы генератора.

Любопытно, что несложной модификацией алгоритма можно заставить его "перескакивать" сразу на несколько бит, как будто подпрограмма была вызвана несколько раз. Если перескакивать каждый раз на 8 бит - то 8 из 16 разрядов такого генератора уже гораздо лучше подойдут в качестве 8-битных случайных чисел. Эта технология называется "Leap-ahead LFSR", можно погуглить и сразу найти описание.

introspec
06.04.2014, 21:21
LFSR дает хорошие случайные биты, но вот использовать все биты состояния в качестве 8- или 16-разрядных случайных чисел не рекомендуется: они все-таки довольно сильно коррелируют между соседними раундами работы генератора.
Это понятно. Кстати, с учётом скорости работы этого генератора, есть потенциал замесить биты, чтобы получался более-менее приличный "случайный" байт. Вот вариант на 30 тактов:
add h ; 4
and %10101010 ; 7
ld h, a ; 4
ld a, l ; 4
and %01010101 ; 7
or h ; 4Пока что генератор Baze мне всё ещё нравится больше, но он работает 136 тактов, т.е. запас есть.

introspec
07.04.2014, 12:22
Я думаю, что вот это - самый быстрый генератор байтов "индустриального" качества:
rnd ld hl,0xA280 ; yw -> zt
ld de,0xC0DE ; xz -> yw
ld (rnd+4),hl ; x = y, z = w
ld a,l ; w = w ^ ( w << 3 )
add a,a
add a,a
add a,a
xor l
ld l,a
ld a,d ; t = x ^ (x << 1)
add a,a
xor d
ld h,a
rra ; t = t ^ (t >> 1) ^ w
xor h
xor l
ld h,e ; y = z
ld l,a ; w = t
ld (rnd+1),hl
retЭтот генератор был написан Патриком Раком (Patrik Rak) и опубликован на WoS в 2008 году (http://www.worldofspectrum.org/forums/showpost.php?p=583693&postcount=3). Процитированный выше код был слегка дооптимизирован Einar Saukas (http://worldofspectrum.org/forums/showpost.php?p=651670&postcount=86). Он выдаёт новый псевдослучайный байт за 122 тактa процессора.

Если скорость не критична, я бы рекомендовал использование именно этого генератора; он быстрее многих генераторов в этом треде, не требует большого буфера, а математически - намного, намного совершеннее LSFR.

Titus
07.04.2014, 13:21
Я думаю, что вот это - самый быстрый генератор байтов "индустриального" качества

А что за алгоритм в основе?

introspec
07.04.2014, 13:27
А что за алгоритм в основе?
Алгоритм называется Xor-Shift, вот ссылка на статью, описывающую идеологию таких генераторов: http://www.jstatsoft.org/v08/i14/paper
Партику пришлось заново пересчитать константы генератора, т.к. в статье основной упор на тройки 32-х битных слов, а Патрик переделал алгоритм для четвёрки восьмибитных, для удобства реализации на Z80.

ram_scan
07.04.2014, 16:58
Алгоритм называется Xor-Shift, вот ссылка на статью, описывающую идеологию таких генераторов:

Это классический образец генератора на сдвиговом регистре с обратной связью. Только насколько я понимаю он с 32битным "семечком". Полином считать мне лениво.

introspec
07.04.2014, 17:02
Это классический образец генератора на сдвиговом регистре с обратной связью. Полином считать мне лениво.Да-да, так его, так, научите Джорджа Марсалью писать ГСЧ, научите...

ram_scan
07.04.2014, 18:17
Да-да, так его, так, научите Джорджа Марсалью писать ГСЧ, научите...

Ну, во первых если я что-либо в чем-либо понимаю то сверьху не M-генератор.

Во вторых зачем его учить ? Дональд Кнут всех в 50-е годы научил обобщив высшую математику для MIX машины. С той поры собсно ничего нового не придумали пока еще.

Достаточно открыть книжку и прочитать, не изобретая велосипеда. Я прочитал.

introspec
07.04.2014, 18:26
Джордж Мерсалья прославился в своё время тем, что доказал математически, в чём заключается проблема с генераторами на сдвиговом регистре. Вы тоже можете проделать простое упражнение, генерируя случайные числа своим генератором и строя точки, с координатами X и Y взятыми из идущих подряд случайных чисел. Картинка, я думаю, вас удивит.

Мерсалья - был, до своей недавней смерти, ведущим специалистом по ГСЧ в мире. Он придумал схемы половины всех более-менее распространённых ГСЧ. Он создал библиотеку тестирования ГСЧ, тесты в которой наверняка проходит только один генератор в этом треде.

ram_scan
07.04.2014, 19:05
Джордж Мерсалья прославился в своё время тем, что доказал математически, в чём заключается проблема с генераторами на сдвиговом регистре.

Я где-то утверждал обратное ?



Мерсалья - был, до своей недавней смерти, ведущим специалистом по ГСЧ в мире. Он придумал схемы половины всех более-менее распространённых ГСЧ. Он создал библиотеку тестирования ГСЧ, тесты в которой наверняка проходит только один генератор в этом треде (100% не ваш).


Во первых я не спорил с тем что Марсалья специалист. Во вторых все все генераторы в этом треде - на сдвиговом регистре с обратной связью. В третьих вы проверьте "мой" генератор, что предположения строить. В четвертых - я не утверждал что мой лучший. Это просто классическая реализация из кнута. Я писал что в теме есть откровенно плохие генераторы.



При этом, вы даже не знали, что полиномы для максимального периода неединственные.

И где я это за все полиномы говорил ? Я утверждал что для некоторых условий есть единственные. Насколько мне известно для 16битного полинома существует только один вариант дающий последовательность длиной 65535. Если вам известны другие - велкам.



При этом, вам лениво считать полином для метода, который вы не понимаете, не понимая, что LFSR у вас там в упор не получится.

XorShift явлется частным случаем LFSR. Внезапно. XorShift работает хуже LFSR. Это плата за минимализм.

Генератора Макларена-Марсальи на который вы видимо пытаетесь ссылаться как на лишенный большинства недостатков я в теме в упор не вижу.

introspec
07.04.2014, 19:58
Во первых я не спорил с тем что Марсалья специалист. Во вторых все все генераторы в этом треде - на сдвиговом регистре с обратной связью. В третьих вы проверьте "мой" генератор, что предположения строить. В четвертых - я не утверждал что мой лучший. Это просто классическая реализация из кнута. Я писал что в теме есть откровенно плохие генераторы.
Я проверил ваш генератор (равно как и все остальные генераторы в этой теме, кроме генератора, процитированного alone, т.к. меня не устраивает его расход памяти). Вот ваша цитата: "Для сдвигового 16-битного регистра с обратной связью такой полином только один, который я и использовал", на основании которой я делал моё заключение. Именно поэтому я выкладывал вам ссылку на все полиномы начиная с 8 и заканчивая не помню сколькими битами.


XorShift явлется частным случаем LFSR. Внезапно. XorShift работает хуже LFSR. Это плата за минимализм.
Но вот на этом месте я публично облажался. Я был неправ, прошу прощения. Если у вас есть ссылки на тему "XorShift работает хуже LFSR", я бы хотел на них посмотреть.

Shadow Maker
07.04.2014, 22:05
Собственно, может вернемся тогда к тестированию ваших ПСЧ? Есть у нас реализация тестов от того же Марсальи для Спектрума? Я про эти (http://ru.wikipedia.org/wiki/Тесты_DIEHARD). Если нет - возможно нужно сделать, а то сколько можно меряться заполнением экрана... Конечно, так-то можно последовательность нагенерить и потом её на PC протестировать, но это же не наш метод...

introspec
07.04.2014, 22:36
Собственно, может вернемся тогда к тестированию ваших ПСЧ? Есть у нас реализация тестов от того же Марсальи для Спектрума? Я про эти (http://ru.wikipedia.org/wiki/Тесты_DIEHARD). Если нет - возможно нужно сделать, а то сколько можно меряться заполнением экрана... Конечно, так-то можно последовательность нагенерить и потом её на PC протестировать, но это же не наш метод...Нечего тестировать. Патрик Рак гонял свой генератор на DIEHARD (практически наверняка, все тесты он не проходит), а остальные не пройдут и подавно из-за короткого внутреннего состояния (шансы есть только у генератора приведённого alone). Лично меня интересовали в основном экстремально быстрые генераторы (100 тактов и меньше), эту задачу я для себя выполнил.

denpopov
11.04.2014, 19:01
вылетело из головы, как называется распределение случайных чисел - Гаусса-Коши-Лапласа?

предлагаю "тараканьи бега":
в исходнике мой вариант и introspec'a

introspec
11.04.2014, 19:08
вылетело из головы, как называется распределение случайных чисел - Гаусса-Коши-Лапласа?

предлагаю "тараканьи бега":
в исходнике мой вариант и introspec'aА какой из генераторов использован в бегах? и если несколько, как их переключать? Тот генератор, кот. сделан по-умолчанию, работает не ахти - самый первый таракан летит, как будто ему пинка под зад дали.

denpopov
11.04.2014, 19:51
Тот генератор, кот. сделан по-умолчанию, работает не ахти - самый первый таракан летит, как будто ему пинка под зад дали.

процедура random - это та, что я привел.
вторая процедура - твоя.

introspec
11.04.2014, 20:14
процедура random - это та, что я привел.
вторая процедура - твоя.
Всё, я понял. Ну вот собственно ещё одно свидетельство того, что быстрый генератор далеко не суперхорош.

denpopov
11.04.2014, 20:27
Ну вот собственно ещё одно свидетельство того, что быстрый генератор далеко не суперхорош.
собственно нет. мне процедура досталась давным-давно и найдена неизвестно где.
Но я не утверждаю, что генератор хорош:)

introspec
11.04.2014, 20:49
собственно нет. мне процедура досталась давным-давно и найдена неизвестно где.
Но я не утверждаю, что генератор хорош:)
Чисто проговорю чтобы можно было понять со стороны: в этом конкретном тесте, найденная незнамо где процедура работает лучше 66т генератора.

---------- Post added at 17:49 ---------- Previous post was at 17:37 ----------

...но если бы ты замешал биты, как я показывал вот здесь: http://forum.tslabs.info/viewtopic.php?f=3&t=391 , или взял бы не первый, а второй генератор оттуда же, даже без замешивания, то получилось бы по крайней мере не хуже и всё ещё быстрее.

denpopov
17.04.2014, 08:14
кстати, такой вопрос - как получить случайное число из диапазона, например random(60)?

ничего другого в голову не пришло, как int(rnd()/255*60)

psb
17.04.2014, 11:23
можно rnd()%60

Barmaley_m
18.04.2014, 16:59
ничего другого в голову не пришло, как int(rnd()/255*60)
Все правильно. Только зачем делить на 255? Это нужно, только если исходные случайные числа находятся в диапазоне 0..255.

Остаток от деления и (что равносильно) выделение младших бит не рекомендуется делать в тех книгах, которые я читал о генераторах случайных чисел. Обычно "качество" старших бит в генераторах лучше.

denpopov
18.04.2014, 17:32
Только зачем делить на 255? Это нужно, только если исходные случайные числа находятся в диапазоне 0..255.
потому что под rnd() я имел в виду ту функцию, которая выдает случайное число.

ram_scan
19.04.2014, 17:28
потому что под rnd() я имел в виду ту функцию, которая выдает случайное число.

Брать остаток от деления, делить нацело, либо пользовать какой-то иной фрагмент от значения ГСЧ верно только в случае когда ГСЧ является именно ГСЧ (и то сильно не всегда).

Если оперировать цифровым ГПСЧ, то можно наступить на реальные грабли, и тут уже "какой кусочек брать если меня разрядность не устраивает" играет очень заметную роль.

В большинстве случаев либо делят нацело и берут остаток от деления, либо просто делят нацело (применительно к z80 исключительно дорогая в плане машинного времени процедура если не по степени двойки). Если разрядность позволяет - маскируют. Но тут нужно читать классиков, потому-что бездумное применение конкретных метод для конкретных генераторов ПСЧ может дать откровенно плохой выхлоп.

Хотя опять-же, смотря для чего это надо. В принципе для игрушки чтобы врагов рожать достаточно наверное любого из генераторов которые были в теме опубликованы (ну кроме пары откровенно плохих, что собственно сами авторы публикуя их и признавали).

denpopov
19.04.2014, 17:40
"какой кусочек брать если меня разрядность не устраивает
честно говоря, для меня это темный лес.
просто возникла такая необходимость в вычислении случайных чисел из диапазона.

ram_scan
19.04.2014, 18:24
честно говоря, для меня это темный лес.
просто возникла такая необходимость в вычислении случайных чисел из диапазона.

Если по степени двойки можно замаскировать старшие биты. Если не по степени двойки - поделить нацело или взять остаток от деления нацело.

Но качество результата очень сильно зависит от того как устроен генератор ПСЧ.

Никто не говорит что так нельзя делать. Так иногда нельзя делать. Если вас результат устраивает (вряд-ли вы пишете криптостойкую софтину, да и генераторы тут опубликованные не для таковой) то пользуйтесь на здоровье и не грейте себе голову =) Перфекционизм - не всегда хорошо.

denpopov
23.04.2014, 10:15
еще из раскопок, слишком много на винте скачанного файла. Субботник!


; Fast RND
;
; An 8-bit pseudo-random number generator,
; using a similar method to the Spectrum ROM,
; - without the overhead of the Spectrum ROM.
;
; R = random number seed
; an integer in the range [1, 256]
;
; R -> (33*R) mod 257
;
; S = R - 1
; an 8-bit unsigned integer

ld a, (seed)
ld b, a

rrca ; multiply by 32
rrca
rrca
xor 0x1f

add a, b
sbc a, 255 ; carry

ld (seed), a
ret

aGGreSSor
06.10.2025, 01:26
Сижу с генераторами ПСЧ8 для Вектор-06Ц.
Написалось три генератора, все 3 - отстой и работают кое-как, но делюсь.
Если у кого-то есть лучше - дайте знать.


; random_xorshift
; вход: E - верхняя граница
; выход: A - псевдослучайное число [0, E]
RND8: push h
push d
lhld SEED ; Загружаем состояние
; XOR-shift алгоритм
mov a, h
rrc ; Сдвиг вправо
mov h, a
mov a, l
rlc ; Сдвиг влево
mov l, a
xra h ; XOR между H и L
mov h, a
shld SEED ; Сохраняем новое состояние
mov a, l ; Берем случайное число
cmp e ; Ограничиваем диапазоном [0, E]
jc RDONE
MLX: sub e
cmp e
jnc MLX
RDONE: pop d
pop h
ret

SEED: db 13h



; RND Дениса Попова переводим на 8080, вариант №1
; вход: E - верхняя граница
; выход: A - псевдослучайное число [0, E]
RND8: lda SEED
mov B,A
stc ; rrca 1
cma
rar
cma
stc ; rrca 2
cma
rar
cma
stc ; rrca 3
cma
rar
cma
xri 0x1f ; A=A xor 0x1f
add B ; A=A+B
sbi 255 ; A=A-255-CY
sta SEED
cmp E
jnc RND8 ; если >= E, генерим по новой
ret

SEED: db 13h


; RND Дениса Попова переводим на 8080, вариант №2
; вход: E - верхняя граница
; выход: A - псевдослучайное число [0, E]
RND8: lda SEED
mov B,A
rar ; rrca 1
jnc RR2
ori 80h
RR2: rar ; rrca 2
jnc RR3
ori 80h
RR3: rar ; rrca 3
jnc RR4
ori 80h
RR4: xri 0x1f
add b
sbi 255 ; приплыли
sta SEED
cmp E
jnc RND8 ; если >= E, генерим по новой
ret

SEED: db 13h


- - - Добавлено - - -

Есть ещё инновационный подход.
1) Пишем за минуту программу на питоне
2) Генерируем нужное нам кол-во псевдослучайных чисел в нужном диапазоне
3) Загоняем в таблицу
4) По этой таблице и ходим в своей программе, чтобы не иметь себе мозг. Enjoy
:rolleyes:

Shiny
09.10.2025, 07:20
RND Дениса Попова
Этот код был взят из программы Life, опубликованной в Spectrofon. Вот дизассемблер, который я сделал, Ден у меня одолжил(:

goodboy
29.12.2025, 10:48
в древнейшей игре SabreWulf наткнулся на курьёзную ситуацию.
генератор псевдо-случайных чисел (в качестве начального отсчёта) использует значение из переменной (frames)
и всё бы ничего, но (frames) используется в `навешенной` защите (замеряется время между окончанием загрузки и стартом игры).
после проверки прерывания запрещены и игра стартует с фиксированным значением в (frames).
в итоге размещение ключевых предметов всегда одинаково.
(ситуация справедлива только для фирменной версии игры)