Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Генератор случайных чисел.


Генератор случайных чисел.

Сообщений 31 страница 53 из 53

31

Итак. Закончил я свои мытарства со случайными числами. Сначала испробовал вариант с __rseed. Он не намного лучше, чем просто RND. Последовательность другая, но она практически повторяется при следующем включении. Измениться может одно число из пяти, но основная последовательность одинаковая. __rseed брал разные значения. С таймером 1 получилось намного лучше. Последовательность чисел практически не предсказуема. Специально подключил терминал, чтобы весь вечер перед плеером не просидеть. Пробовал три раза, специально начинал с первого файла.
1  34  7    221  311  224  145  287  24  81  143 191 250
1 121 169  41  101  220  247  234 299 151 175  31  54
1  87 246 131   75  179   111   72 183  313 151  26  51
Значения абсолютно разные и не повторяются. Только таймер пришлось конфигурировать в главном цикле, после получения общего количества файлов. Получилось вот так:

Код:
 If Flag_timer1 = 0 Then
 Set Flag_timer1                        ' поднимаем флаг, чтобы config 1 раз
    Config Timer1 = Timer , Prescale = 1024
   Compare1a = All_tracks             ' максимальное значение
   Enable Timer1 : Start Timer1
   End If

И после ответа плеера о завершении проигрывания трека:

Код:
Stop Timer1
Track_number = Timer1 Mod All_tracks
If Track_number = &H0000 Then Track_number = &H0001
Byte4 = &H03 : Byte6 = Track_hi : Byte7 = Track_low
Gosub Transmit                                   ' отправляем в плеер
Start Timer1

Все работает, как надо. Спасибо всем за помощь и участие.

0

32

Нашли приемлемый вариант - респект ! ;)

Небольшое "исследование":
Значение __rseed необходимо (!) менять перед стартом RND.
В этом случае генерация RND будет однозначно отличаться от предыдущей.

Попробовал с таймерами (не знаю, насколько стратегия совпала с вашей), попробовал просто RND, попробовал с __rseed...
Заполнял таблицу, как описано ранее...

По времени (окончания процесса) "победил" вариант с использованием __rseed... ;)
Таблица из 3000 неповторяющихся значений была заполнена за 0,4сек на МК ATMega32 8MHz

0

33

__rseed изменял и при старте программы и перед RND. Больших изменений не увидел.

0

34

Я в своё время в "лампе настроения" развел на плате "змейку", дорожку в виде зигзага максимально заполнив пустые области и поближе к МК, после этого подключил её на АЦП.
В момент включения замерял значение АЦП, приводил его в норму, дабы не превысить величину rseed и присваивал его rseed.
Всё работало прекрасно. Вместо разводки дорожки можно просто припаять провод, типа антенна и приклеить его к плате.
Конечно лучше использовать специальные стабилитроны или транзисторы, которые сильно шумят, но для простого случая можно и так.

Отредактировано sva-don (2019-04-05 09:54:55)

0

35

Вариантов получения значения для rseed - море.

Главное - перед очередной генерацией RND заменить значение rseed.
Достаточно даже rseed = rseed + 5, например - уже будет новая последовательность.
Делал так в #32... ;)

0

36

А если ещё каждое значение RND записывать в EEPROM (чтобы при включении схемы его от туда забирать в __rseed), то будет ещё интереснее.

+1

37

RDW написал(а):

А если ещё ...

+100500
Надо начинать собирать "банк" способов получения rseed... ;)
Интересно, на сколько фантазии хватит у форумчан ? ;)

+1

38

Я конечно за аналоговый рандом, но в своё время мне так не удалось его обуздать (времени не было), да и если проанализировать его, то он может быть не таким уж и случайным (ибо помехи бывают весьма закономерны). Получается, что аналог нужен для старта функции RND и только. А дальше уже извращаемся в меру надобности результата.

0

39

Nord написал(а):

+100500
Надо начинать собирать "банк" способов получения rseed...
Интересно, на сколько фантазии хватит у форумчан ?

Если нет особых требований, то псевдослучайный RND.
Если требования повышенные, то в качестве источника случайных чисел обычно используют переход эмиттер-база биполярного NPN транзистора из-за низкого пробойного напряжения.
Снятый с перехода шум усиливается и преобразовывается в цифровой сигнал.
Случайные числа с подобных ГСЧ проходят все статистические тесты, однако скорость их генерации крайне мала — менее 10 Кбит/с.

0

40

RDW написал(а):

А если ещё каждое значение RND записывать в EEPROM (чтобы при включении схемы его от туда забирать в __rseed), то будет ещё интереснее.

Я вот так и делаю, то есть пытаюсь сделать. Но нифига не получается.

Код:
Dim __rseed As Word
     ....................
track_number = track_number_eep    'номер последнего игравшего трека
__rseed = track_number

Потом, в главном цикле, после того как плеер сообщает, что он закончил играть очередной трек

Код:
__rseed = Track_number        ' приисваиваем rseed знач. последнего трека
Track_number = Rnd(all_tracks)       ' случ. число из общего кол-ва треков
' дальше отправляю номер трека в плеер

Последовательность одна и та же. Что я делаю не так?

0

41

Кажется понял. Должно быть так:

Код:
Track_number = Rnd(__rseed)

Но, тогда получается, если __rseed присваивать текущее значение RND, то последовательность будет стремится к нулю. Значение больше __rseed мы уже получить не сможем. Поэтому в ХЕЛПЕ и предлагают использовать для этих целей таймер.

0

42

У вас track_number участвует во всем... ;)
Сначала в нее загоняете значение из ЕЕР...
Потом она оказывается номером последнего проигранного...
И опять используется в генерации...

Логика верна, но на каком этапе она меняется ?  Не видно...

Andrusha написал(а):

Track_number = Rnd(__rseed)

Вообще ерунда... ;)

Отредактировано Nord (2019-04-06 23:29:03)

0

43

Попробовал генерировать RND в Протеусе этим кодом:

Код:
Do

For c = 1 To 3
___rseed = c * 5
Print c
Print

For b = 0 To 100
      a = Rnd(3000)
      Print a
Next b

Next c

Loop

Вот что получилось:

Свернутый текст

1        2         3
       
2132    85    574
2567    1660    753
2030    1679    864
657    2390    659
2192    2809    2962
1411    2432    453
1282    459    2172
301    2298    1759
204    21    2838
2471    812    2617
2206    2951    1160
2785    70    355
1696    2497    298
2091    1864    1637
1666    1355    1044
1805    2034    1799
652    1397    1678
783    2572    1361
2766    327    424
2369    1366    827
1440    337    1770
1587    1768    2413
530    371    676
941    18    2095
2204    2709    214
391    132    2873
830    1303    2240
2297    2934    1035
1544    1289    570
931    1800    2205
994    395    260
2669    2370    2071
1980    1309    174
2791    1220    2185
662    231    2336
1529    502    2939
272    1313    2354
475    224    437
1322    387    2452
413    1818    687
2172    1229    750
2335    2492    113
2382    1143    2904
2025    2726    891
744    2833    2386
2179    624    1605
1634    2307    444
2597    1482    2903
1508    2821    1134
55    604    689
1254    927    136
673    2798    1923
1224    2737    786
2467    1264    2597
194    43    2428
1717    2626    71
2644    2045    982
2303    2820    801
862    1543    2688
1969    2446    387
1832    2057    2746
299    1336    2837
586    627    1132
1125    1442    2223
1772    397    2022
1575    260    1945
2006    2415    288
2801    1790    779
1296    1145    994
635    960    1285
1074    1875    2676
1853    1050    247
1084    1229    1374
295    1116    1473
2270    431    1128
2593    2558    2059
2272    1497    1186
363    1864    2901
850    1819    2788
1253    178    2567
2308    2573    302
887    652    881
2918    2623    2328
2841    478    1579
488    1    2514
1907    240    1573
2570    347    660
821    1482    1679
2564    1781    1462
2311    2452    2593
142    2879    2152
2969    2134    835
1600    1153    1170
299    1280    1797
2890    2419    1948
445    690    471
1044    813    1046
991    2244    33
62    623    720
2865    2326    2251
1800    1841    2346

Не наблюдаю "кучи повторов"... ;)

0

44

"раньше" 1993г.  для проверки "чистоты" RND использовали следующий весьма наглядный метод.
Делалась СОБСТВЕННАЯ процедура RND и её результат выводился на стандартный VGA адаптер IBM PC AT с разрешением 640Х480 в монохромном режиме.
Dot (rnd(640), rnd(480))
Сразу было видно заполнение точек, равномерное или нет.
Можно и в одномерной плоскости придумать счётчик повторов за единицу времени.

0

45

Nord написал(а):

Попробовал генерировать RND в Протеусе этим кодом:

Да дело не в том, что RND плохо работает, а в том, что при каждом перезапуске контроллера будет одна и та же последовательность. :no:
Эта тема широко освещена в инете. Если нужна неповторяющаяся последовательность при каждом включении без внешнего генератора шума не обойтись.

0

46

А, ну это да, так и будет.
Я делаю проще: EOR с датой, временем с RTC и вперёд.

0

47

sva-don написал(а):

Да дело не в том, что RND плохо работает, а в том, что при каждом перезапуске контроллера будет одна и та же последовательность.  Эта тема широко освещена в инете. Если нужна неповторяющаяся последовательность при каждом включении без внешнего генератора шума не обойтись.

ИМХО, для какого-то плейера мастырить генератор шума - жирно... ;)
Вполне достаточно будет привязки к имеющимся "часам". К любой "части" времени.
И это не дает гарантии, что сразу же услышим тот же трек, что и звучал перед последним выключением...
"RND аднака"...

Цель изначально понятна - при включении устройства получить RND-плейлист.
Сталкиваюсь с этим периодически в автомобиле, где в гамнитоле включен случайный выбор воспроизведения с флешки, но при этом "случайном" наблюдаю повторы...

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

0

48

Спасибо всем за помощь. Ничего адекватного не получилось. Пробовал просто RND, пробовал RND  с ___rseed, пробовал свой код, пробовал код Nord'a. Последовательность при включении одна и та же. Это в железе, с выводом на терминал. Остановлюсь на своем варианте с таймером 1. Спасибо всем.

0

49

Andrusha написал(а):

Пробовал просто RND, пробовал RND  с ___rseed, пробовал свой код, пробовал код Nord'a. Последовательность при включении одна и та же.

Интересно... Аж даже загорелся... ;)

Только что проверил "свой код" из #43 с выводом на Терминал через переходник USB-UART на Mega48...
Результат подтверждается...

Вообще-то интересная тенденция...
Во времена QB функция RND отрабатывала очень даже адекватно...
Затем, видимо, "правообладатель" этой функции уволился ;) и "мелкомягким" пришлось искать альтернативу в последующих диалектах Basic...
Появился оператор RANDOMIZE (то же самое, что и ___rseed в Bascom)...
А истинная предыстория адекватного RND ушла в небытие вместе с "правообладателем"... ;)

Надо заняться этим вопросом как-нибудь (адекватная генерация RND)... ;)

0

50

-NMi- написал(а):

У него "иногда" только получаеццо,

У меня хоть иногда получается. У тебя же лучше всего получается языком ляпать.  :P
Nord, а не может это зависеть от версии Баскома? У меня 2.0.8.1, ломаная.

0

51

Andrusha написал(а):

а не может это зависеть от версии Баскома? У меня 2.0.8.1, ломаная.

ХЗ... ;)
Не раз тут пролетали утверждения, что "нелицензия" неправильно работает... ;)
У меня 2.0.7.8 с "ключом в комплекте".

0

52

Nord написал(а):

Затем, видимо, "правообладатель" этой функции уволился  и "мелкомягким" пришлось искать альтернативу в последующих диалектах Basic...

Если говорить про диалекты бейсика, то далеко не все они от микрософта и баском тому подтверждение. :D

Nord написал(а):

А истинная предыстория адекватного RND ушла в небытие вместе с "правообладателем"

И сейчас есть диалекты с  адекватным random. :)
Например https://www.purebasic.com/download.php
Обычный random.

Код:
OpenWindow(0, 0, 0, 322, 150, "Гаджет Редактор", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
EditorGadget(0, 8, 8, 306, 133)
For a = 0 To 500
  AddGadgetItem(0, a, RSet(Hex(Random($FF), #PB_Long), 2, "0"))
Next
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Криптографический Random.

Код:
OpenCryptRandom()

OpenWindow(0, 0, 0, 322, 150, "Гаджет Редактор", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
EditorGadget(0, 8, 8, 306, 133)
For a = 0 To 500
  AddGadgetItem(0, a, RSet(Hex(CryptRandom($FF), #PB_Long), 2, "0"))
Next
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

CloseCryptRandom()

http://rgho.st/6LC7qJhr8

0

53

Andrusha написал(а):

Спасибо всем за помощь. Ничего адекватного не получилось. Пробовал просто RND, пробовал RND  с ___rseed, пробовал свой код, пробовал код Nord'a. Последовательность при включении одна и та же. Это в железе, с выводом на терминал. Остановлюсь на своем варианте с таймером 1. Спасибо всем.

Если будешь писать в ЕЕПРОМ последние значение и при старте его читать (с него стартовать), то как минимум, повторения при включении не будет. И если даже будут два устройства с этим алгоритмом, то как минимум, если список проигрывания и люди разные (вкусовые пристрастия), то на выходе тоже будет разное случайное число при старте.

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Генератор случайных чисел.