Важная информация

User Tag List

Страница 2 из 4 ПерваяПервая 1234 ПоследняяПоследняя
Показано с 11 по 20 из 32

Тема: Генерация случайных чисел в заданном диапазоне

  1. #11
    Activist Аватар для Raider
    Регистрация
    24.06.2005
    Адрес
    novosibirsk
    Сообщений
    266
    Записей в дневнике
    5
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    1
    Поблагодарили
    1 сообщение
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Кстати LFSR отличаются тем что генерируют псевдослучайную последовательность именно бит.
    Вот еще: https://en.wikipedia.org/wiki/Xorshift

    а кинь плиз еще форумов/блогов где advanced кодинг для спектрума/z80 обсуждают? (можно в ЛС)

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

    Цитата Сообщение от Bedazzle Посмотреть сообщение
    оба ответа "да".
    Разве что с поправкой, что 8 бит это 256
    Имелось в виду максимальная битовая репрезентация. MAXUINT для 8-bit

    График добавлен как предостережение тем, кто мог набежать и невдумчиво использовать вместо серьёзного генератора.
    Регистр в 8bit определяет очень короткую длину последовательности, через 256 чисел она зацикливается (если не раньше, бугага, надо вообще-то проверить). Поэтому не надо заполнять такие большие площади/графики такими короткими последовательностями, надо увеличить их длину, т.е. юзать регистровые пары.
    Alex Raider, Flash inc. 1992-1997 Новосибирск

  2. #12
    Veteran
    Регистрация
    26.11.2013
    Адрес
    г. Новосибирск
    Сообщений
    1,041
    Спасибо Благодарностей отдано 
    931
    Спасибо Благодарностей получено 
    224
    Поблагодарили
    121 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Oleg N. Cher, попробуй что-то вроде:
    Код:
    return (_Basic_RandBB()*(max-min+1) ) >> 16 + min;

  3. #13
    Veteran Аватар для Oleg N. Cher
    Регистрация
    24.08.2007
    Адрес
    Днепропетровская обл.
    Сообщений
    1,593
    Спасибо Благодарностей отдано 
    2,158
    Спасибо Благодарностей получено 
    130
    Поблагодарили
    96 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Думаешь, умножение и сдвиг будут эффективнее взятия по модулю?

    Господа, в итоге, видимо, задача сводится к эффективному вычислению модуля для байтов и слов. Если модуль байтового значения ещё можно как-то лопатить с помощью вычитание-пока-не-будет-заёма+сложение (хотя это оптимизация больше по размеру, чем по скорости), то для слов надо придумать что-то поинтереснее.

    Ещё интересно про использование регистра R в генераторах ПСЧ или СЧ. Как можно использовать этот регистр, не теряя равномерность диапазона (не сбиваясь на более частое выпадение одних значений над другими)?

  4. #14
    Activist Аватар для Raider
    Регистрация
    24.06.2005
    Адрес
    novosibirsk
    Сообщений
    266
    Записей в дневнике
    5
    Спасибо Благодарностей отдано 
    0
    Спасибо Благодарностей получено 
    1
    Поблагодарили
    1 сообщение
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
    Ещё интересно про использование регистра R в генераторах ПСЧ или СЧ. Как можно использовать этот регистр, не теряя равномерность диапазона (не сбиваясь на более частое выпадение одних значений над другими)?
    R это же самый обычный счетчик.
    Это работает только если пользователь создает какой-то случайное событие (нажатие клавиши клавиатуры, джойстика) в котором проходит некоторый случайный интервал времени от предыдущего взятия R и по этому событию читается R.

    Если полагаться на R в программном коде которому требуется сколько-то псевдослучайных значений (например в цикле) — ничего хорошего заведомо не выйдет.
    Последний раз редактировалось Raider; 11.01.2017 в 20:38.
    Alex Raider, Flash inc. 1992-1997 Новосибирск

  5. #15
    Veteran
    Регистрация
    08.05.2007
    Адрес
    Dnepropetrovsk
    Сообщений
    1,053
    Спасибо Благодарностей отдано 
    218
    Спасибо Благодарностей получено 
    47
    Поблагодарили
    31 сообщений
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Поддерживаю всё сказанное Raider. В качестве быстрого генератора случайных чисел лучше всего подойдет именно линейный конгруэнтный генератор. В книге "Numerical Recipes" я видел специально подобранные значения констант, которые позволяют несколько упростить вычисление. "Стандартный" генератор использует формулу:

    S := (a*S + c) mod m

    где S - состояние генератора, которое также возвращается в виде случайного числа после каждой итерации; a, c, m - константы.

    то упрощенный генератор позволяет исключить сложение:

    S := (a*S) mod m

    это требует тщательного подбора констант, в книге приведены значения a=7^5=16807; m=2^31-1 = 2147483647

    Для этого требуется 32-битная арифметика, но авторы книги категорически предостерегают от использования генераторов ПСЧ с 16-битным состоянием из-за слишком малого периода повторения.

    Линейный конгруэнтный генератор дает числа в диапазоне от 0 до m-1. Чтобы получить другой диапазон, необходимо провести дополнительное умножение на константу. Так, если 0<=x<m, то 0<x*(n/m)<n. Константа n/m будет в общем случае дробной, но дробные вычисления с фиксированной точкой в сущности ничем не отличаются от целочисленных.

  6. #16
    Veteran
    Регистрация
    26.11.2013
    Адрес
    г. Новосибирск
    Сообщений
    1,041
    Спасибо Благодарностей отдано 
    931
    Спасибо Благодарностей получено 
    224
    Поблагодарили
    121 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
    Думаешь, умножение и сдвиг будут эффективнее взятия по модулю?
    Может и эффективнее, если эффективнее оптимизируется, но важнее, что старшие биты более качественно случайны, чем младшие.

  7. #16
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  8. #17
    Veteran Аватар для Oleg N. Cher
    Регистрация
    24.08.2007
    Адрес
    Днепропетровская обл.
    Сообщений
    1,593
    Спасибо Благодарностей отдано 
    2,158
    Спасибо Благодарностей получено 
    130
    Поблагодарили
    96 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    А, вот оно что.

    А мог бы кто-нить, не особо углубляясь в теорию, набросать код ПСЧ для задаваемого диапазона? В принципе, меня устроит и генератор в диапазоне 0..255, к которому прикручено циклическое взятие по модулю. Мож где-то готовый есть хороший. А то вижу про 32-битную арифметику, и так ломает всё это кодить на асме. %)

  9. #18
    Veteran Аватар для Bedazzle
    Регистрация
    02.05.2015
    Адрес
    г. Таллин, Эстония
    Сообщений
    1,485
    Спасибо Благодарностей отдано 
    219
    Спасибо Благодарностей получено 
    149
    Поблагодарили
    115 сообщений
    Mentioned
    9 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Цитата Сообщение от Raider Посмотреть сообщение
    "качество" ПСЧ-последовательности можно простейшим способом анализировать путем взятия двух соседних отсчетов и отображения их по X,Y.
    Если между X и Y существует корреляция, то точки начнут выстраиваться в какие-либо структуры (чаще полоски) и заполнение экрана будет не равномерным.
    Да, так и есть.


  10. #19
    Veteran
    Регистрация
    01.03.2005
    Адрес
    Новосибирск
    Сообщений
    1,979
    Спасибо Благодарностей отдано 
    69
    Спасибо Благодарностей получено 
    261
    Поблагодарили
    99 сообщений
    Mentioned
    6 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Точно

    Нажмите на изображение для увеличения. 

Название:	sshot000001.png 
Просмотров:	270 
Размер:	6.8 Кб 
ID:	59398

    Нажмите на изображение для увеличения. 

Название:	sshot000000.jpg 
Просмотров:	320 
Размер:	19.9 Кб 
ID:	59397

  11. #20
    Veteran
    Регистрация
    08.05.2007
    Адрес
    Dnepropetrovsk
    Сообщений
    1,053
    Спасибо Благодарностей отдано 
    218
    Спасибо Благодарностей получено 
    47
    Поблагодарили
    31 сообщений
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

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

    Современным наиболее широко применяемым, эффективным методом генерации случайных чисел является алгоритм Mersenne Twister. Если стандартные реализации ориентированы на сверхдлинный период повторения, то от ребят из Хиросимы существует реализация, ориентированная на малость потребляемых ресурсов. Она может подойти для Спектрума. Ее период повторения - 2^128-1, что намного лучше, чем практически реализуемые на Спектруме линейные конгруэнтные генераторы.

    Вот ссылка на проект: https://github.com/MersenneTwister-Lab/TinyMT

    Основные вычисления производятся в файле tinymt32.h, функции "tinymt32_next_state" и "tinymt32_temper". Всё остальное - вспомогательный код. Вот текст этих функций вместе с объявлением структуры состояния генератора:

    Код:
    struct TINYMT32_T {
        uint32_t status[4];
        uint32_t mat1;
        uint32_t mat2;
        uint32_t tmat;
    };
    
    inline static void tinymt32_next_state(tinymt32_t * random) {
        uint32_t x;
        uint32_t y;
    
        y = random->status[3];
        x = (random->status[0] & TINYMT32_MASK)
    	^ random->status[1]
    	^ random->status[2];
        x ^= (x << TINYMT32_SH0);
        y ^= (y >> TINYMT32_SH0) ^ x;
        random->status[0] = random->status[1];
        random->status[1] = random->status[2];
        random->status[2] = x ^ (y << TINYMT32_SH1);
        random->status[3] = y;
        random->status[1] ^= -((int32_t)(y & 1)) & random->mat1;
        random->status[2] ^= -((int32_t)(y & 1)) & random->mat2;
    }
    
    inline static uint32_t tinymt32_temper(tinymt32_t * random) {
        uint32_t t0, t1;
        t0 = random->status[3];
    #if defined(LINEARITY_CHECK)
        t1 = random->status[0]
    	^ (random->status[2] >> TINYMT32_SH8);
    #else
        t1 = random->status[0]
    	+ (random->status[2] >> TINYMT32_SH8);
    #endif
        t0 ^= t1;
        t0 ^= -((int32_t)(t1 & 1)) & random->tmat;
        return t0;
    }
    Copyright (c) 2011, 2013 Mutsuo Saito, Makoto Matsumoto,
    Hiroshima University and The University of Tokyo.
    All rights reserved.
    
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are
    met:
    
        * Redistributions of source code must retain the above copyright
          notice, this list of conditions and the following disclaimer.
        * Redistributions in binary form must reproduce the above
          copyright notice, this list of conditions and the following
          disclaimer in the documentation and/or other materials provided
          with the distribution.
        * Neither the name of the Hiroshima University nor the names of
          its contributors may be used to endorse or promote products
          derived from this software without specific prior written
          permission.
    
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    Обратите внимание, что не используются операции умножения и деления, а только сдвиги и логические операции. Так что есть хороший шанс, что все это быстро заработает на Z80.

    Лицензия - BSD

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

    Нашел еще один, еще более быстрый, простой и качественный генератор - Xorshift.

    Код вообще элементарный:
    Код:
    #include <stdint.h>
    
    /* The state word must be initialized to non-zero */
    uint32_t xorshift32(uint32_t state[static 1])
    {
    	uint32_t x = state[0];
    	x ^= x << 13;
    	x ^= x >> 17;
    	x ^= x << 5;
    	state[0] = x;
    	return x;
    }
    Никаких умножений и делений, только сдвиги и ксор. Период повторения - 2^32-1.

    Сгенерировал 10000 чисел - вроде выглядят случайно, последовательность не повторяется, спектр белый. Так что скорее всего метод работает. Но выглядит до ужаса просто!

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

    Навскидку код для Z80 (не тестировал)
    Код:
    ; The RNG state (32 bits), must be initialized to nonzero
    state:    db 1
                db 1
                db 1
                db 1
    ; Based on the current state of the RNG, updates the state to the next RNG. The result is saved into the state variable
    ; And also returned in DE:HL registers.
    rand:    ld hl,(state)
               ld de,(state+2)
               ld b,13
               call shl
               cal xorstate
               ld b,17
               call shr
               call xorstate
               ld b,5
               call shl
               jr xorstate
    
    ; Shift left a 32-bit number in DE:HL by B bits
    shl:    sla l
            rl h
            rl e
            rl d
            djnz shl
            ret
    
    ; Shift right an unsigned 32-bit number in DE:HL by B bits
    shr:    srl d
            rr e
            rr h
            rr l
            djnz shr
            ret
    
    ; Xors the current state (4 bytes) with DE:HL, returns result in both DE:HL and the state
    xorstate:
            ld bc,(state)
            ld a,l
            xor c
            ld l,a
            ld a,h
            xor b
            ld h,a
            ld (state),hl
            ld bc,(state+2)
            ld a,e
            xor c
            ld e,a
            ld a,d
            xor b
            ld d,a
            ld (state+2),de
            ret

Страница 2 из 4 ПерваяПервая 1234 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Ответов: 54
    Последнее: 10.08.2020, 14:28
  2. генератор случайных чисел на БК
    от litwr в разделе БК-0010/0011
    Ответов: 6
    Последнее: 28.09.2018, 14:06
  3. Генерация синуса
    от Hacker VBI в разделе Программирование
    Ответов: 154
    Последнее: 02.06.2014, 15:54
  4. Генерация лабиринтов
    от TomCaT в разделе Программирование
    Ответов: 90
    Последнее: 26.06.2012, 10:59

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •