Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.73/22: Рейтинг темы: голосов - 22, средняя оценка - 4.73
Fangod
8 / 8 / 0
Регистрация: 07.10.2011
Сообщений: 164
1

Генерация случайных чисел

20.11.2014, 14:04. Просмотров 4047. Ответов 9
Метки нет (Все метки)

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

Использовал такой метод
C++
1
2
3
4
5
x = число по которому будет генерироваться рандом
m = 255 // Будем использовать это число
a = x % 10 // Получим последнюю цифру числа x
с = 1 // Если вдруг x = 0
r = ((x % 10) * x + 1) % 255
В итоге функция генерации рандома по ключу, выгладила как-то так:
C++
1
2
3
x = Системный таймер, количество тиков ОС
r = ((x % 10) * x + 1) % 255
Math.floor((1 / r) * (max - min)) + min;
Но при прогоне цикла от 0 до 1000 получалось немного не то, что я ожидал
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.11.2014, 14:04
Ответы с готовыми решениями:

Генератор Псевдо Случайных Чисел на языке СИ
Тема - Генерация псевдослучайных чисел в задаваемом диапазоне Решил написать программу для ГПСЧ...

Assembler Atmega16 Генератор случайных чисел
Мне нужно получить число с помощью таймера T0 CTC OCR0:=255, присвоить его переменной. На чертеже...

Задача такое нужно построить случайных величин и генерация случайных чисел(ГСЧ
Народ помогите тут надо. Задание такое нужно построить случайных величин и генерация случайных...

Генерация случайных чисел с учётом уже имеющихся чисел. (C++ Builder 6)
Здравствуйте. Появилось желание создать программу генерации случайных чисел с учётом уже имеющихся...

Генерация случайных чисел
Здравствуйте, появилась такая проблема: при генерации случайного числа функцией rand(); мне нужно...

9
pyzhman
1161 / 516 / 76
Регистрация: 15.05.2012
Сообщений: 2,959
20.11.2014, 14:26 2

Не по теме:

Взял жену. Перелопатил кучу инфы что с ней делать. Но получалось немного не то, что я ожидал.


А каковы были ожидания?
0
Fangod
8 / 8 / 0
Регистрация: 07.10.2011
Сообщений: 164
20.11.2014, 14:29  [ТС] 3
Генерация в диапазоне min - max
0
pyzhman
1161 / 516 / 76
Регистрация: 15.05.2012
Сообщений: 2,959
20.11.2014, 14:36 4
Смотрим что нам дает флур:
returns the smallest integer value of the floating point number x.
Второе. Судя по вашему описанию, переменные байтовые.
Итого имеем - что останется от 1/r? ну пусть даже помноженное на что-то там.
PS. Уравнение толком составьте для конгруэнтного.
PPS. Вику читали хотя бы?
0
20.11.2014, 14:36
Fangod
8 / 8 / 0
Регистрация: 07.10.2011
Сообщений: 164
20.11.2014, 15:22  [ТС] 5
Я уже понял прокол с 1 / r
В оригинале, функция rang() возвращает 0.xxxxxxx...
Я хотел сдвинуть число, т.е. из r сделать 0.r, и поделил 1 на него, почему-то подумалось, что так сработает

Добавлено через 9 минут
Вику читал, ещё пару статей и презентаций, и щас все ещё ищу инфу и поглядываю на форум

Добавлено через 33 минуты
Вдруг кому пригодиться, написал скрипт для проверки алгоритмов в консоли, он считает кол-во выпавших чисел
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Минимальное и максимальное значение
var min = 5, max = 10;
 
// Функция нашего рандома, 
// где x - число, на основе которого генерируеться рандом
// min и max - диопозон
function rand(min, max, x){
    var r = ((x % 10) * x + 1) % 255;
    var end = r % (max - min + 1) + min;
    return  end;
}
 
 
// Остальное не трогать
function rand2(min, max){
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
var arr = {}, arr2 = {}, logtext = '';
for(var i = min; i <= max; i++){
  arr[i] = 0;
  arr2[i] = 0;
}
for(var i = 0; i <= 100000; i++){
  arr[rand(min, max, i)]++;
  arr2[rand2(min, max)]++;
}
for(var key in arr){ 
  logtext += key + '=' + arr[key] + '; ';
}
console.log(logtext);
logtext = '';
for(var key in arr2){
  logtext += key + '=' + arr2[key] + '; ';
}
console.log(logtext);
Видно, что стандартная функция js выдает достаточно хорошее распределение
5=16692; 6=16693; 7=16417; 8=16828; 9=16625; 10=16746;
В то время как самописная не очень
5=10587; 6=35294; 7=9806; 8=9411; 9=24705; 10=10198;
0
ValeryS
Модератор
7944 / 5915 / 783
Регистрация: 14.02.2011
Сообщений: 20,347
Завершенные тесты: 1
20.11.2014, 16:49 6
Fangod,
А чем функция rand() не устроила?
если нужно действительно случайное число, а не псевдослучайную последовательность
то можно попробовать такой метод
ножку микроконтроллера удлиняем, делаем что то типа антенны
а потом при помощи АЦП считываем уровень
эфирные помехи близки к "белому шуму"
может придется приделать усилитель и ФНЧ чтобы исключить наводку 50Гц
0
Fangod
8 / 8 / 0
Регистрация: 07.10.2011
Сообщений: 164
20.11.2014, 16:54  [ТС] 7
Допустим, я считал уровень с АЦП, пусть будет 893
Мне нужно случайное число от 2 до 7, как его высчитать? В этом и проблема, не могу найти алгоритм который из ключа будет генерировать случайное число с равномерным распределением, я хочу использовать счетчик тиков RTOS, это тоже сойдет не хуже, чем значения с АЦП
0
ValeryS
Модератор
7944 / 5915 / 783
Регистрация: 14.02.2011
Сообщений: 20,347
Завершенные тесты: 1
20.11.2014, 17:01 8
Цитата Сообщение от Fangod Посмотреть сообщение
Допустим, я считал уровень с АЦП, пусть будет 893
а зачем?
Цитата Сообщение от Fangod Посмотреть сообщение
Мне нужно случайное число от 2 до 7,
вот и считывай от 0 до 7(три разряда)
Цитата Сообщение от Fangod Посмотреть сообщение
В этом и проблема, не могу найти алгоритм который из ключа будет генерировать случайное число с равномерным распределением,
не надо генерировать
помехи и дадут случайное число
Цитата Сообщение от Fangod Посмотреть сообщение
я хочу использовать счетчик тиков RTOS, это тоже сойдет не хуже, чем значения с АЦП
гораздо хуже
счетчик тиков известен и если ты будешь их считывать с определенным периодом то повторяемость на лицо
а со случайным периодом, то как вычислить случайность периода?

и еще раз спрошу? чем не устроила стандартная Сишная функция rand()?
1
Fangod
8 / 8 / 0
Регистрация: 07.10.2011
Сообщений: 164
20.11.2014, 19:13  [ТС] 9
Стандартная функция выдает одну и туже последовательность
Счетчик может быть и работает с определенным периодом, но вот событие при котором происходит надобность в рандоме абсолютна случайная (робот натолкнулся на препятствие), и предсказать значение счетчика невозможно

Нашел то, что нужно, но не работает, проверил сначала на JS, потом на шарпе, зацикливает на 0.8183099494386802


Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Константы, предложеные Lewis, Goodman и Miller 
var IA = 16807;
var IM = 2147483647;
var AM = 1.0 / IM;
/* Константы предложеные Scharge */
var IQ = 12773;
var IR = 2836;
// Специальная маска
var MASK = 123456789;
 
// Установка начального зерна
var dummy = 345335;
function Seed(dum) {
  dummy = dum;
}
// Возвращает распределеные числа от 0 до 1 
function unirand0(){
  var k;
  var ans;
  dummy ^= MASK;
  k = dummy / IQ;
  if((dummy = IA * (dummy - k * IQ) - IR * k) < 0 ){ 
    dummy += IM;
  }
  ans = AM * dummy;
  dummy ^= MASK;
  return ans;
}
 
for(var i = 0; i <= 30; i++){
  console.log(unirand0());
}
Добавлено через 1 час 27 минут
Проверил на c++, тоже самое, зацикливает на 0.8....
Неужели нигде нет решения?

Добавлено через 26 минут
Так, форматнул код, проверил на плюсах, вроде что-то нормальное, потом протестирую
Наверно, кому-нибудь это понадобиться
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "stdafx.h"
#include <iostream>
using namespace std;
 
 
// Константы
#define NTAB 32
#define NWUP 8
#define EPS 1.2e-7
#define RNMX (1.0 - EPS)
#define IM1 2147483563
#define IM2 2147483399
#define AM (1./IM1)
#define IMM1 (IM1-1)
#define IA1 40014
#define IA2 40692
#define IQ1 53668
#define IQ2 52774
#define IR1 12211
#define IR2 3791
#define NDIV (1 + IMM1 / NTAB)
 
// Зерно
static long dummy;
void Seed(long dum) { 
    dummy = dum; 
}
 
float custom_rand(void) {
    int j;
    long k;
    static long dummy2 = 123456789;
    static long iy = 0;
    static long iv[NTAB];
    float temp;
    if(dummy <= 0 || !iy) {
        if(dummy < 0) { 
            dummy = -dummy; 
        } else if(dummy == 0) { 
            dummy = 1;
        }
        dummy2 = dummy;
        for(j = NTAB + NWUP - 1; j >= 0; j--) {
            k = dummy / IQ1;
            if((dummy = IA1 * (dummy - k * IQ1) - IR1*k) < 0) { 
                dummy += IM1;
            }
            if(j < NTAB) { 
                iv[j] = dummy; 
            }
        }
        iy = iv[0];
    }
    k = dummy / IQ1;
    if((dummy = IA1 * (dummy - k * IQ1) - IR1 * k) < 0) { 
        dummy += IM1;
    }
    k = dummy2 / IQ2;
    if((dummy2 = IA2 * (dummy2 - k * IQ2) - IR2 * k) < 0) { 
        dummy2 += IM2;
    }
    iy = iv[j = iy / NDIV] - dummy2; 
    iv[j] = dummy;
    if(iy<1) { 
        iy += IMM1; 
    }
    if((temp = AM*iy)>RNMX) { 
        return RNMX; 
    }
    return temp; 
}
 
 
 
int _tmain(int argc, _TCHAR* argv[]){
    // Ключ, любое число
    Seed(6443567589);
    for(int i = 0; i <= 1000; i++) {
        cout << custom_rand() << endl;
    }
    system("pause");
    return 0;
}
0
Voland_
1736 / 1069 / 107
Регистрация: 04.01.2010
Сообщений: 3,654
22.11.2014, 11:01 10
Цитата Сообщение от Fangod Посмотреть сообщение
Стандартная функция выдает одну и туже последовательность
для встроенного рандомайза есть начальный сид, который задает эту последовательность. Он задается командом random (по-моему так). В качестве аргумента - 16 битное число. Вставляйте в аргумент значение вашего таймера, если вы так ему доверяете, периодически (например раз в секунду, минуту или час), чтобы сбивать последовательность. Таким образом псевдослучайность станет еще случайнее...

Но, то что вам советовали - юзать младшие биты АЦП в качестве источника случайного сигнала - это наиболее приемлемый вариант.

Что касается диапазона [2..7] так воспользуйтесь элементарной математикой - генерите число в любом диапазоне, берите остаток от деления числа на размер нужного диапазона и прибавляйте смещение.
0
22.11.2014, 11:01
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.11.2014, 11:01

Генерация случайных чисел
Здравствуйте! Мне нужно сгенерировать случайные числа, много и за секунду или быстрей. Можно ли...

Генерация случайных чисел
Как в С сгенирировать последовательность случайных чисел от x до y.Например от 1 до 100.

Генерация случайных чисел
Здрасти. В общем нужно сгенерировать случайное число никак ни связанное с предыдущими числами. При...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.