Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как функцией rand() получить число от 0 до 2 ?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
-=Женек=-
Как функцией rand() получить число от 0 до 2 ?
Да и объясните про srand() я каждый раз в цикле вызываю srand(rand()); но на работу rand() это не оказывает влияния.

короче говоря у меня есть массив Current[3], его нужно заполнить числами от 0 до 2

for (y=0;y<3;y++)
{
srand(rand());
Current[y]= что здесь?

}
IgorKossak
Функция int rand(void) возвращает целое число в диапазоне [0, RAND_MAX].
Функция void srand(int seed) служит для задания начального значения случайной последовательности.
Для Вашего случая слишком маловат диапазон, или Вы хотите результат с плавающей точкой?
Пример лучше переписать так:
Код
#define RAND_MAX 2000
for (y=0;y<3;y++)
{
    srand(5);      // любое число не = 1
    Current[y] = (float)rand() / 1000.0;   // если это массив значений float
}
Petka
Цитата(IgorKossak @ Jan 13 2008, 14:50) *
Функция int rand(void) возвращает целое число в диапазоне [0, RAND_MAX].
Функция void srand(int seed) служит для задания начального значения случайной последовательности.
Для Вашего случая слишком маловат диапазон, или Вы хотите результат с плавающей точкой?
Пример лучше переписать так:
Код
#define RAND_MAX 2000
for (y=0;y<3;y++)
{
    srand(5);      // любое число не = 1
    Current[y] = (float)rand() / 1000.0;   // если это массив значений float
}


ЭЭЭ! srand() надо вынести ЗА цикл. Иначе получите просто одинаковые значения при каждом вызове rand()!
zltigo
Цитата(IgorKossak @ Jan 13 2008, 13:50) *
Пример лучше переписать так:
Код
for (y=0;y<3;y++)
{
    srand(5);      // любое число не = 1
    Current[y] = (float)rand() / 1000.0;   // если это массив значений float
}

Ошибка. Это псевдослучайный генератор, который стабильно будет повторять последовательность при
одинаковом исходном значении. Посему, как минимум, srand() вне цикла:
Код
srand(5);      // любое число не = 1
for (y=0;y<3;y++)
{
.........
}
-=Женек=-
мне не нужна плавающа точка.
Ваш пример не работает. Не могу к сожалению проверить, что он выдает, от числа получаемого фоункцией зависит номер зажигаемого светодиода - в моем случае не горит ничего.
Пишу в CodeVision
zltigo
Цитата(-=Женек=- @ Jan 13 2008, 14:21) *
от числа получаемого фоункцией зависит номер зажигаемого светодиода

1. Число лежит в диапазоне от 0 до RAND_MAX, кое обычно (посмотрите в stdlib.h) не менее 16bit, посему нужно нормализировать до диапазона 0...2 перед употреблением.
2. Уже писал - самое главное rand() НЕ ГЕНЕРИТ СЛУЧАЙНЫЕ ПОСЛЕДОВАТЕЛЬНОСТИ, посему получить четыре случайных числа при каждом запуске не сможете.
ReAl
Цитата(IgorKossak @ Jan 13 2008, 13:50) *
Функция int rand(void) возвращает целое число в диапазоне [0, RAND_MAX].
...
Пример лучше переписать так:
Код
#define RAND_MAX 2000
for (y=0;y<3;y++)
{
    srand(5);      // любое число не = 1
    Current[y] = (float)rand() / 1000.0;   // если это массив значений float
}

А-а-а!!! У-у-у!!! lol.gif
Нет, ну я не могу сдержаться, чесслово.
А сделать
Код
#define LONG_MAX  7
#define LONG_MIN  -8
и таким образом ограничить диапазон значений long никто не пробовал? Рекомендую!
А если вдруг я ещё не все комнаты смеха посетил и где-то есть компилятор, настолько не соответствующий стандарту, что переопределение RAND_MAX в пользовательском коде вот так просто влияет на поведение библиотечной rand() - адресок сбросьте, а!

-=Женек=-, думаю, для светодиодов каких-то особых качеств генератора не нужно и этого хватит с головой (если вообще использовать библиотечный rand() )
Код
#include <stdlib.h>

unsigned char led_rand()
{
    unsigned char r;
    do {
        r = rand() & 0x03;
    } while( r == 3); // тута ошибочка была, исправлено
    return r;
}

srand() вызывать вообще не обязательно. Ну если хочется, чтобы каждый раз при включении не повторялась 1:1 последовательность (всё равно когда-то выйдет на цикл, но хоть чтобы не стартовало каждый раз с разного места) - то надо делать srand() с каким-то "внешне-случайным" аргументом - содержимым какого-то свободно-бегущего атймера в момент нажатия пользователем какой-то кнопки, ещё что-то такое найти.
zltigo
Цитата(ReAl @ Jan 13 2008, 15:33) *
А-а-а!!! У-у-у!!! lol.gif
Код
        r = rand() & 0x03;
}

Так просто не отделаетесь smile.gif - Автор хотел диапазон 0...2 а не 0...3
Цитата
srand() вызывать вообще не обязательно.

Ну хоть какой-то элемент случайности smile.gif ввиде однократного выбора при программировании вызов srand() c аргументом отличным от 1 вносит...
Rst7
Цитата
Так просто не отделаетесь - Автор хотел диапазон 0...2 а не 0...3

....
Цитата(ReAl @ Jan 13 2008, 15:33) *
Код
do {
        r = rand() & 0x03;
    } while( r != 3);

Так там цикл, пока результат=3, повторять. Чето тема получилась веселейшая. На наших гуру и шаманов видимо торможение напало smile.gif - Старый Новый год, чтоли?

Цитата
Хороший генератор, как цвет автомобиля у Генри Форда


Черт. И я торможу. Там конечно должно быть while(r==3)

Все, на сегодня с форумом надо завязывать. smile.gif
ReAl
Да, конечно, while( r == 3), это я глюкнул - не успокоился ещё, а уже писать начал - и сам народ повеселил biggrin.gif
-=Женек=-
Господа, ну конкретный результат кто-нибудь может выдать?
Сергей Борщ
Цитата(-=Женек=- @ Jan 13 2008, 17:43) *
Господа, ну конкретный результат кто-нибудь может выдать?
Current[y] = rand() / (RAND_MAX / 3);
Арифметика, пропорции, четвертый класс.
-=Женек=-
брр... а RAND_MAX тогда чему равен? И к чему эти деления,
если я изначально пропишу его как 3?
Kirill Trusov
я конечно салага но 3 вопроса
1. для какого компилятора , винавр?
2. разве не надо было брать rand()%2 брать целое от деления, вроде на си так в прогах писал когда надо было псевдослучаееноость

3. а вообще есть такая библиотека для авр, т.е на основании чаво она генерирует числа? не проще ли записать какойто набор чисел случаенных и по ним ходить по кругу, всяко ранд тоже псевдослучаенные дает
zltigo
Цитата(Сергей Борщ @ Jan 13 2008, 18:21) *
Current[y] = rand() / (RAND_MAX / 3);
Арифметика, пропорции, четвертый класс.

Сергей! Ты, конечно, не поверишь!! но это правда!!! - твой ответ неверен!!!! sad.gif
При значении rand() == RAND_MAX ты получишь число 3 smile.gif
Осталось чуть-чуть подправить, но на этом пути есть еще одна проблемка. Не наступи!

Цитата(-=Женек=- @ Jan 13 2008, 18:34) *
брр... а RAND_MAX тогда чему равен?

Не принципиально, а где конкретное значение посмотреть я писал.


Цитата(Kirill Trusov @ Jan 13 2008, 18:41) *
1. для какого компилятора , винавр?

Любого сишного. Это ANSI, однако.
На счет остального пока помолчу, дабы интрига осталась....
-=Женек=-
Цитата
я конечно салага но 3 вопроса
1. для какого компилятора , винавр?


Салага, наверное, я, но уже было написано выше, что компилятор CodeVision


Цитата
unsigned char led_rand()
{
unsigned char r;
do {
r = rand() & 0x03;
} while( r == 3); // тута ошибочка была, исправлено
return r;
}



Возвращает всегда 0 (((

ПОЛЦАРСТВА за
РАБОЧИЙ лишенный всяких философских непонятных абстракций
пример для CodeVision генерирующий любоей из 0,1,2 чисел.

Маленькая просьба, отвечать только тех, кто проверил это у себя на компе.

С уважением.
zltigo
Цитата(-=Женек=- @ Jan 13 2008, 19:35) *
Возвращает всегда 0 (((

Это невозможно, если только CodeVision компилятор "C" а не "языка похожего на C". Должен выдавать числа в требуемом диапазоне. Единственно, что вероятность нескольких нулей подряд отнюдь не мала, а повторяемость, как тут было уже трижды написано, 100%, поскольку rand() есть просто генератор ПСЕВДОСЛУЧАЙНОЙ последовательности однозначно задаваемой аргументом при вызове srand(). Про генерацию "случайных" , Вам ReAl рассказал.
Единственно, что максимально близкий к рабочему каноническому варианту описан в п.2 у Kirill Trusov.
-=Женек=-
Знаете, за что я благодарен форуму?
Пока дождешься пока кто-нибудь ответит, доходит до самого.
Вот код, который у меня работает
Цитата
for (y=0;y<3;y++) Current[y]=(unsigned int)((rand()-2768)/10000);
zltigo
Цитата(-=Женек=- @ Jan 13 2008, 20:26) *
Вот код, который у меня работает

Произвольные действия над псевдослучайным числом, естественно, могут выдавать разные цифири. Вы хоть поняли, что делаете?

Все очень просто делается. Просто берется остаток от деления на 3. Вот и все smile.gif.
-=Женек=-
Я прекрасно понимаю что делаю, это вы не понимаете мой код, с чего вы взяли, что я беру остаток от деления? Я беру случайное число, вычитаю из него 2768, чтобы результат был не выше 29999, делаю с ним (unsigned int), чтобы результат не был отрицательным. Далее делю на 10000 и беру результат, а не остаток от деления. В тоге получаю 0,1 или 2.
zltigo
Цитата(-=Женек=- @ Jan 13 2008, 20:45) *
Я беру случайное число, вычитаю из него 2768, чтобы результат был не выше 29999, делаю с ним (unsigned int), чтобы результат не был отрицательным. Далее делю на 10000 и беру результат

Вот результат Вы себе и не представляете sad.gif.
1. результат зависит от MAX_RAND, который отнюдь не обязан бвть 0x7FFF
2. При подаче на вход случайной последовательности получите искажение исходного распределения вероятности.
Цитата
, а не остаток от деления.

Я учился в школе, по этой причине я не мог говорить, что Вы берете остаток от деления, я говорил, что НАДО ПРОСТО ВЗЯТЬ ОСТАТОК ОТ ДЕЛЕНИЯ.
Код
   Current[y] = rand() % 3;
-=Женек=-
И что? ну пусть будет 31232, делим на 3, получаем 232.

Вот вам 5 чисел:

15325
10234
00323
23954
31222

ПРоделайте свой код с каждым из них в письменном виде здесь на форуме и выложите результат.


Цитата
1. результат зависит от MAX_RAND, который отнюдь не обязан бвть 0x7FFF


Кстати, MAX_RAND менял - не помогало.
Rst7
Цитата
ПРоделайте свой код с каждым из них в письменном виде здесь на форуме и выложите результат.


1, 1, 2, 2, 1

А Вы это сделали? Не путайте операцию "/" (деление) с операцией "%" (остаток от деления)
Сергей Борщ
Цитата(zltigo @ Jan 13 2008, 20:51) *
НАДО ПРОСТО ВЗЯТЬ ОСТАТОК ОТ ДЕЛЕНИЯ.
Верхняя математика мне давалась тяжело, поэтому вопрос - будет ли остаток иметь такое же распределение, как и исходное число? Интуитивно чувствую, что частное будет, а остаток?

Цитата(zltigo @ Jan 13 2008, 19:09) *
Сергей! Ты, конечно, не поверишь!! но это правда!!! - твой ответ неверен!!!! sad.gif
При значении rand() == RAND_MAX ты получишь число 3 smile.gif
Ну ладно, подколол, подколол smile.gif Current[y] = rand() / ((RAND_MAX + 1) / 3). Ну и еще подумать об округлениях. Тогда ((RAND_MAX + 2) / 3).

Цитата(-=Женек=- @ Jan 13 2008, 20:45) *
делаю с ним (unsigned int), чтобы результат не был отрицательным. Далее делю на 10000 и беру результат
Посмотрите внимательнее свой код - вы преобразуете к (unsigned int) результат после деления, а не до.
Цитата(-=Женек=- @ Jan 13 2008, 21:02) *
Кстати, MAX_RAND менял - не помогало.
Библиотечный макрос называется RAND_MAX. ReAl вам пытался объяснить, что RAND_MAX менять не нужно - она задана вам "свыше" автором библиотеки. И как бы вы ее не меняли - код, скомпилированный в библиотеку об этом ничего не знает. Переопределяя RAND_MAX вы можете только сделать ваш код обработки (если он использует RAND_MAX) несовместимым с библиотечной функцией, ничего больше.
Rst7
Другое дело, что деление сюда прикладывать как-то совсем не хочется. Так что я бы делал что-то типа

unsigned int i=(unsigned int)rand()/((RAND_MAX+1)/256);
i=i+i+i;
i>>=8;

В результате деление в первой строке (если RAND_MAX не совсем психозный) будет преобразовано к сдвигу (причем, специально каст к unsigned, чтобы знак не расширять) и даст результат 0..255, потом мы его умножим на 3 (сложением, чтобы компилятор не дай бог не позвал процедуру умножения) и разделим на 256 - получим результат от 0 до 2, с таким же распределением, как и rand.

Вроде нигде не промахнулся...
ReAl
Я дал рабочий пример (с учётом поправки, сначала по ошибке написал while(r != 3) а надо while( r == 3) ).
Как правило я проверяю код перед отправкой, но тут не проверял, так как был уверен в работоспособности (в случае применения вменяемого компилятора С и достаточно стандартной библиотекой).

Нужна проверка? "Их есть у меня"
CODE
#include <stdio.h>
#include <stdlib.h>

unsigned char rnd3(void)
{
unsigned char val;
do {
val = rand() & 0x03;
} while( val == 3);
return val;
}


unsigned char rnd3div(void)
{
return ((rand()-2768)/10000);
}

unsigned char rnd3mod(void)
{
return rand() % 3;
}


void test( char *header, unsigned char (*rndfunc)(void), int count)
{
int i, prev;
int gist[3] = {0};
int gist2[3][3] = { {0} };

printf("\n-------------------------------\n%s\nvalue table\n", header);

prev = rnd3();
for( i = 0; i < count; ++i) {
unsigned char r = rndfunc();
printf( (i & 0x1F) == 0 ? "\n%2d" : "%2d" , r );
++gist[r];
++gist2[prev][r];
prev = r;
}

printf("\n\n%s - frequency table\n", header);
for( i = 0; i < 3; ++i)
printf( "%d -> %3d\n", i, gist[i] );

printf("\n%s - prev/curent frequency table\n", header);
printf(" 0 1 2\n");

for( i = 0; i < 3; ++i)
printf( "%d%6d%6d%6d\n", i, gist2[i][0], gist2[i][1], gist2[i][2] );

}


int main(void)
{
test( "rand() & 0x03", rnd3, 1024);
test( "(rand() - 2768) / 10000", rnd3div, 1024);
test( "rand() % 3", rnd3mod, 1024);

return 0;
}


mingw32-gcc -O2 -s rnd3.c -o rnd3.exe
rnd3 >rnd3.txt

CODE

-------------------------------
rand() & 0x03
value table

2 0 1 0 2 2 2 0 1 1 1 1 2 0 0 2 1 0 2 1 0 2 2 2 1 0 2 2 1 1 0 1
1 0 0 2 1 1 1 1 2 0 2 2 0 2 0 2 0 0 2 1 2 1 2 2 2 1 1 0 1 0 2 0
0 2 0 0 0 2 1 2 2 2 1 1 1 2 0 2 1 2 1 2 1 1 0 0 2 1 1 1 1 0 2 2
1 0 2 0 2 2 1 0 2 2 1 1 1 1 1 1 2 1 0 2 2 2 2 1 0 0 2 2 0 1 0 1
2 2 0 2 0 0 1 0 0 0 1 2 1 2 2 0 0 0 1 0 1 2 1 1 2 1 0 0 1 0 2 0
0 0 1 1 2 1 1 2 0 0 2 2 0 0 2 1 1 2 1 1 0 2 2 0 2 2 1 2 0 0 2 2
0 0 2 2 2 1 1 2 0 0 1 2 2 1 1 0 0 1 0 0 2 1 1 0 1 1 2 1 2 1 0 2
1 1 0 0 1 2 1 1 0 1 0 0 1 2 1 1 0 1 0 2 1 0 1 1 1 2 1 1 1 0 2 1
0 2 2 2 1 0 2 1 1 1 0 0 0 1 1 0 1 2 2 2 1 0 0 2 1 1 2 1 2 0 0 1
0 2 2 1 1 2 1 2 2 0 2 1 2 2 1 1 2 2 0 2 2 0 1 2 1 2 1 1 2 0 0 1
2 0 1 2 1 0 0 1 1 0 1 1 1 0 2 2 2 0 0 0 1 2 2 2 1 0 0 1 2 0 2 0
1 0 2 2 2 2 2 1 0 2 0 0 0 0 2 2 1 2 0 2 0 1 2 2 1 1 2 1 1 0 0 2
2 0 1 1 1 0 0 2 0 2 2 1 0 2 0 0 0 2 1 0 1 2 2 1 1 0 2 0 1 0 1 0
1 1 2 0 0 1 0 1 0 0 0 0 2 1 0 0 2 1 2 1 1 1 1 0 2 1 0 1 0 1 1 1
1 1 0 0 1 2 0 2 2 0 1 1 0 0 2 2 2 1 1 1 2 2 2 1 2 2 1 1 2 1 2 0
1 0 1 2 0 1 0 1 1 2 2 1 0 2 0 0 1 0 1 0 2 2 1 0 0 1 0 0 1 2 1 1
2 1 1 2 0 0 2 0 1 0 1 1 0 0 1 1 0 1 1 1 0 1 2 1 1 1 0 0 1 0 2 0
0 2 2 2 0 1 2 2 1 0 0 2 1 0 2 0 2 1 2 2 0 0 0 1 1 0 2 2 1 2 1 1
0 1 0 1 0 2 2 1 0 0 0 2 1 0 1 1 0 0 1 1 1 1 0 2 0 0 1 2 2 0 2 2
1 2 0 0 0 2 1 2 1 1 0 0 1 2 0 2 2 1 1 1 0 0 0 2 1 2 0 0 0 2 2 1
1 0 1 2 0 1 1 0 0 1 2 2 0 0 0 2 2 2 1 1 1 2 2 2 2 2 1 1 0 0 0 2
1 2 2 0 0 0 1 1 1 0 0 0 2 2 2 1 0 0 1 2 1 1 0 2 1 2 0 2 1 2 0 1
1 0 0 1 1 2 1 2 2 1 2 1 2 0 1 1 1 1 1 2 0 0 1 2 0 0 2 2 1 2 0 2
0 1 2 2 1 0 1 0 0 1 1 0 1 2 0 0 2 0 1 2 1 1 0 1 0 1 2 2 1 1 2 0
0 1 0 0 1 1 2 0 0 2 2 1 0 0 2 1 2 1 0 1 2 1 0 1 1 2 2 0 2 2 1 0
0 2 2 1 0 0 2 1 0 0 2 1 0 0 0 2 2 2 0 0 1 2 2 2 2 2 0 2 1 2 2 2
0 1 1 2 2 2 2 0 0 2 0 0 2 0 2 0 1 2 1 0 0 2 1 1 2 1 0 0 0 2 0 1
2 2 2 2 2 0 1 2 1 0 2 2 1 0 1 2 1 0 1 1 2 2 1 1 2 1 0 1 2 1 0 2
0 1 1 1 0 1 0 2 0 0 1 1 0 1 0 2 0 2 0 0 1 0 2 1 1 1 1 1 0 2 1 0
2 1 2 1 0 1 1 1 0 0 2 0 2 2 2 2 2 0 2 0 2 0 2 0 2 0 1 2 1 1 1 2
2 2 1 0 0 0 0 2 0 0 2 0 2 2 1 2 2 0 0 0 0 2 1 2 0 0 2 2 0 0 2 0
2 1 0 2 1 1 2 1 0 0 0 0 2 1 0 0 1 0 1 2 1 1 1 2 0 2 1 0 2 1 1 1

rand() & 0x03 - frequency table
0 -> 336
1 -> 352
2 -> 336

rand() & 0x03 - prev/curent frequency table
0 1 2
0 115 102 119
1 125 120 107
2 96 130 110

-------------------------------
(rand() - 2768) / 10000
value table

1 1 2 1 2 2 2 0 1 2 0 1 0 1 0 0 0 2 1 1 0 0 2 2 0 0 0 0 2 0 0 0
0 2 1 0 0 0 0 1 0 1 0 1 2 0 0 0 1 2 1 2 0 2 2 1 1 1 1 0 2 0 0 0
0 1 2 0 2 0 2 0 0 1 0 0 1 2 0 2 0 2 1 0 0 0 1 0 0 0 0 2 2 1 2 0
1 1 2 0 1 2 2 2 2 1 0 2 0 1 1 1 2 0 1 0 1 0 0 0 0 2 2 0 1 0 2 0
1 2 1 2 1 1 1 1 2 2 0 0 1 0 1 1 2 1 0 1 0 1 2 0 0 1 0 0 2 2 0 0
1 1 2 1 0 1 0 1 2 0 1 2 1 1 1 2 0 0 0 0 0 1 1 0 0 1 0 0 2 1 2 0
0 1 0 0 1 2 0 2 0 2 1 0 0 1 0 1 2 2 0 1 2 2 0 0 2 2 1 0 1 0 1 0
0 2 0 0 0 0 0 0 0 0 0 0 1 2 2 1 2 0 1 1 2 0 2 0 0 2 2 1 2 0 0 0
2 2 1 2 0 2 1 0 2 0 0 0 1 1 1 0 2 0 0 2 1 2 0 0 1 1 1 2 2 0 1 2
0 2 1 0 0 0 0 0 0 2 1 2 0 1 2 2 2 2 0 0 0 2 0 2 0 2 0 0 1 2 0 1
1 0 1 1 2 2 2 1 2 1 0 0 0 2 2 0 0 0 0 0 2 0 1 0 2 1 2 0 1 2 1 1
2 0 0 2 2 0 2 0 2 0 0 0 1 1 1 0 0 0 0 1 0 0 2 1 0 2 2 0 0 2 1 0
0 1 2 1 0 2 1 0 1 2 2 1 1 2 1 0 2 1 0 1 0 0 1 2 0 2 2 1 0 1 1 0
1 1 1 2 0 0 0 0 0 0 1 2 1 0 1 2 2 0 2 0 0 1 0 2 1 0 0 0 2 1 0 0
1 2 1 0 1 2 0 1 1 0 0 1 0 0 1 2 1 0 1 1 1 1 2 0 1 0 0 0 0 1 2 1
1 1 1 1 0 2 0 2 1 2 1 2 1 0 2 2 0 2 0 0 2 2 0 1 0 0 2 1 0 0 1 0
0 0 1 2 1 1 0 0 2 0 0 0 0 0 2 0 0 1 2 1 0 2 0 2 0 2 1 0 2 0 1 2
1 1 0 1 1 0 1 2 0 0 1 2 0 2 2 2 0 1 1 0 0 0 1 0 1 1 2 2 2 1 0 0
0 2 2 1 0 2 1 0 1 2 0 2 0 1 1 0 2 1 1 0 1 2 0 1 0 0 2 2 2 2 1 2
2 1 2 2 0 2 0 1 1 2 2 2 0 1 1 1 1 2 1 0 1 0 2 0 0 2 0 1 0 1 1 0
1 0 0 1 2 2 1 1 0 2 2 0 2 1 1 2 1 0 0 1 2 1 0 1 1 2 2 2 0 0 0 1
1 0 0 0 2 2 0 0 1 2 2 2 0 1 1 1 2 0 2 2 1 2 1 0 2 1 0 0 1 2 1 2
1 2 1 2 0 2 2 2 2 0 0 0 0 2 2 0 0 2 1 0 2 2 1 0 1 1 2 2 2 0 1 2
1 0 1 1 2 1 1 0 0 0 0 1 0 1 2 0 2 1 2 0 0 1 2 2 0 0 1 2 0 1 0 1
0 2 2 2 1 0 0 2 1 1 2 2 2 2 1 1 2 2 0 2 0 0 0 2 2 1 0 0 0 1 2 0
0 1 2 1 0 2 2 1 0 2 1 1 0 2 2 2 1 0 1 2 1 1 0 1 0 2 0 2 2 1 0 1
1 2 2 0 2 1 2 2 1 0 0 0 2 0 0 0 2 2 0 0 0 2 0 2 2 0 1 0 0 0 2 2
0 0 2 2 1 1 0 0 0 2 0 0 0 0 1 0 2 1 1 2 1 2 1 0 0 0 2 2 1 0 1 0
1 0 1 0 1 1 2 2 1 0 2 2 0 0 1 0 2 1 2 1 2 1 2 0 2 2 0 0 0 2 2 1
0 0 0 1 1 2 2 1 2 1 2 0 0 0 1 0 0 2 2 2 1 1 2 0 2 0 1 0 1 0 0 2
1 2 2 1 0 1 1 2 2 2 1 0 0 1 2 1 1 1 0 2 0 2 0 2 0 1 0 0 0 0 0 2
1 0 2 1 1 1 2 1 1 1 0 0 2 2 1 2 2 2 2 0 1 1 2 2 2 1 1 1 2 2 1 0

(rand() - 2768) / 10000 - frequency table
0 -> 402
1 -> 309
2 -> 313

(rand() - 2768) / 10000 - prev/curent frequency table
0 1 2
0 168 123 110
1 121 80 109
2 113 106 94

-------------------------------
rand() % 3
value table

2 0 2 0 1 1 1 2 1 2 0 0 2 1 2 2 2 1 1 0 1 0 1 0 1 2 0 1 0 0 0 1
2 2 2 1 1 1 1 0 0 0 1 1 2 2 2 2 1 1 0 0 0 2 2 0 2 0 2 0 2 1 0 1
2 1 0 1 1 0 1 2 0 0 2 0 2 0 0 2 2 2 2 1 2 2 0 1 1 1 0 2 2 0 2 2
2 0 0 1 1 0 1 0 1 2 0 1 2 2 2 0 0 2 1 0 1 1 2 1 0 1 2 0 1 1 2 1
0 0 2 0 2 1 2 1 2 2 0 1 0 0 0 0 0 0 0 1 2 1 0 1 1 2 2 2 0 2 0 2
1 1 0 1 2 1 0 1 1 0 1 2 1 1 0 2 0 1 1 0 0 2 0 2 1 1 2 1 1 1 1 0
1 0 1 0 0 2 1 1 1 2 2 0 2 1 1 1 0 0 2 2 0 1 2 1 0 2 1 0 1 1 0 1
2 0 2 0 2 2 1 0 0 2 1 0 0 1 0 0 1 2 0 1 1 1 0 2 1 1 1 2 2 0 1 0
0 1 2 0 1 2 1 1 2 2 1 1 0 2 1 1 2 1 0 0 2 1 1 2 2 2 2 0 1 0 2 1
0 1 1 2 0 1 1 1 1 2 2 1 1 2 2 1 2 1 0 2 0 2 1 0 1 2 0 2 2 0 0 1
0 1 2 2 1 1 0 2 0 1 1 1 2 2 0 0 1 1 0 0 2 0 1 2 1 2 1 0 2 0 1 0
2 0 0 0 0 1 2 1 1 1 0 1 2 2 0 2 1 2 0 2 1 2 0 2 2 1 0 0 2 2 2 2
1 1 0 0 2 1 1 1 1 0 0 2 0 2 0 1 1 1 2 1 0 2 0 1 2 0 1 0 1 0 1 2
2 0 2 0 1 0 0 1 2 1 1 0 1 0 1 1 2 1 0 1 0 1 0 1 2 2 1 2 2 2 1 0
0 1 0 1 1 2 1 0 2 2 2 2 0 0 0 1 2 0 1 0 0 0 1 2 2 0 1 1 1 1 0 2
0 0 0 2 2 0 0 1 2 0 2 0 0 1 1 2 2 1 0 0 2 0 0 2 2 1 2 2 0 2 2 2
1 0 1 2 1 0 0 1 2 0 0 1 0 1 1 0 2 0 2 1 2 1 1 2 2 2 0 2 1 1 1 1
2 2 1 0 2 2 0 0 1 2 2 0 1 0 1 0 2 1 2 0 2 1 0 2 2 1 1 0 2 2 0 1
1 0 1 0 0 0 0 1 0 0 1 1 2 1 0 2 2 2 1 2 1 0 0 0 1 2 2 0 0 2 1 1
2 2 0 0 1 0 1 2 2 0 2 0 0 0 2 1 1 2 2 2 1 2 0 0 0 2 2 2 1 0 2 2
0 2 1 0 0 2 0 2 0 0 0 1 1 2 0 1 0 1 0 0 2 1 0 0 0 2 1 1 1 0 0 1
2 0 2 1 2 0 1 2 1 1 2 1 1 2 1 2 2 1 0 2 1 0 1 1 1 0 1 0 0 0 1 1
0 2 2 0 2 1 0 1 0 2 1 0 2 2 0 2 1 0 2 2 1 2 2 2 1 2 1 1 0 0 2 1
2 0 2 1 0 2 2 1 0 2 0 2 0 1 2 0 0 1 2 0 1 2 0 1 1 2 0 0 0 0 2 0
1 0 1 1 0 1 1 1 2 2 2 2 2 1 1 0 1 2 2 2 0 0 1 0 0 0 2 0 2 2 2 1
0 1 0 2 0 1 2 1 1 2 2 0 0 1 2 0 2 1 0 0 0 0 1 1 0 2 2 0 2 0 2 0
2 1 0 0 1 0 0 1 0 1 2 0 0 0 2 2 0 0 0 2 1 2 0 0 1 1 0 2 2 2 0 0
0 0 0 0 1 2 1 0 0 0 0 2 2 1 1 2 1 2 1 2 2 1 2 1 2 2 1 1 2 2 1 0
1 1 0 0 2 0 2 2 0 1 1 2 2 0 2 0 2 0 1 0 1 0 1 2 2 1 1 2 1 0 0 0
2 2 2 2 0 1 0 1 0 2 2 0 1 1 1 2 2 1 0 0 1 0 0 1 2 1 0 1 0 0 0 0
2 1 0 1 1 2 0 1 0 2 2 2 0 2 0 0 2 2 2 2 0 2 1 0 1 1 1 1 0 1 1 2
0 2 2 1 1 2 0 2 1 1 2 1 2 0 0 1 1 0 1 1 1 0 2 1 2 1 2 1 2 1 0 0

rand() % 3 - frequency table
0 -> 348
1 -> 344
2 -> 332

rand() % 3 - prev/curent frequency table
0 1 2
0 109 126 112
1 128 104 112
2 111 114 108


И, чтобы легче сравнивать, только распределения.
Код
-------------------------------
rand() & 0x03 - frequency table
0 -> 336
1 -> 352
2 -> 336

rand() & 0x03 - prev/curent frequency table
      0     1     2
0   115   102   119
1   125   120   107
2    96   130   110

-------------------------------
(rand() - 2768) / 10000 - frequency table
0 -> 402
1 -> 309
2 -> 313

(rand() - 2768) / 10000 - prev/curent frequency table
      0     1     2
0   168   123   110
1   121    80   109
2   113   106    94

-------------------------------
rand() % 3 - frequency table
0 -> 348
1 -> 344
2 -> 332

rand() % 3 - prev/curent frequency table
      0     1     2
0   109   126   112
1   128   104   112
2   111   114   108

Как видим, мой примитив с выдёргиванием двух младших битов и отбрасыванием троек даёт распределения немного хуже, чем "%3", но лучше, чем "/10000".
Зато обходится без деления.

Вообще говоря, гонять нужно было с srand(1) перед каждым тестом и (RAND_MAX+1) проб, а не 1024, но и этого достаточно.
zltigo
Цитата(Сергей Борщ @ Jan 13 2008, 21:14) *
Ну ладно, подколол, подколол smile.gif Current[y] = rand() / ((RAND_MAX + 1) / 3).

Подставился!
А RAND_MAX+1 это сколько? 0 при unsigned или вообще отрицательное число при signed?
Rst7
Цитата
Вроде нигде не промахнулся...


Таки немного промахнулся. Вообщем, примерно вот так надо делать (правда, только IAR под рукой, он конечно, зажыгает)
Код
    165          char rrr(void)
   \                     rrr:
    166          {
    167            unsigned int i=((unsigned int)rand()/(((unsigned int)RAND_MAX+1)/256))&255;
   \   00000000   ........           CALL    rand
   \   00000004   0F00               LSL     R16
   \   00000006   2F01               MOV     R16, R17
   \   00000008   1F00               ROL     R16
    168            i=i+i+i;
    169            i>>=8;
    170            return (char)i;
   \   0000000A   E023               LDI     R18, 3
   \   0000000C   9F20               MUL     R18, R16
   \   0000000E   2D01               MOV     R16, R1
   \   00000010   9508               RET


Без аппаратного умножения тоже все в порядке
Код
      4            unsigned int i=((unsigned int)rand()/(((unsigned int)RAND_MAX+1)/256))&255;
   \   00000000   ....               RCALL   rand
   \   00000002   0F00               LSL     R16
   \   00000004   2F01               MOV     R16, R17
   \   00000006   1F00               ROL     R16
   \   00000008   E010               LDI     R17, 0
      5            i=i+i+i;
      6            i>>=8;
      7            return (char)i;
   \   0000000A   2F20               MOV     R18, R16
   \   0000000C   E030               LDI     R19, 0
   \   0000000E   0F00               LSL     R16
   \   00000010   1F11               ROL     R17
   \   00000012   0F02               ADD     R16, R18
   \   00000014   1F13               ADC     R17, R19
   \   00000016   2F01               MOV     R16, R17
   \   00000018   9508               RET
ReAl
Цитата(zltigo @ Jan 13 2008, 21:31) *
Подставился!
А RAND_MAX+1 это сколько? 0 при unsigned или вообще отрицательное число при signed?

По стандарту rand() имеет тип int и возвращает значения в диапазоне [0, RAND_MAX], так что RAND_MAX <= INT_MAX и (RAND_MAX+1) вполне влазит в unsigned int.
zltigo
Цитата(ReAl @ Jan 13 2008, 21:55) *
вполне влазит в unsigned int.

Влазит, но тогда будет надо корректно явно производить операции с unsigned.
Например, что будет напечатано:
Код
#define SOME 0x7FFFFFFF
int z = SOME;
printf( "Result1=%i\n", z/((SOME+1)/3) );
printf( "Result2=%u \n", z/((SOME+1)/3) );
printf( "Result3=%i\n", ((unsigned int)z)/((SOME+1)/3) );

Это я и имел ввиду,когда писал Сергею
Цитата
Не наступи!
mdmitry
Вопрос в дискуссию: кто-нибудь из авторов вариантов проверял плотность распределения (гистограмму) и корреляционную функцию результата? Там все хорошо со случайностью?
zltigo
Цитата(mdmitry @ Jan 13 2008, 23:44) *
Там все хорошо...

С этим и исходной последовательностью как попало будет, ибо требования к генератору ненормированы абсолютно. Ну а легкие искажения будут, как минимум обусловленные тем, что всесь диапазон генерации ровнехонько на три не делится.
Elegorod
Код
int a = (new java.util.Random()).nextInt(3);

Осталось Java для микроконтроллеров написать smile.gif
Kirill Trusov
Цитата(mdmitry @ Jan 13 2008, 23:44) *
Вопрос в дискуссию: кто-нибудь из авторов вариантов проверял плотность распределения (гистограмму) и корреляционную функцию результата? Там все хорошо со случайностью?


остаток от деления дает хорошее распределение , я делал на си в винде , по 10 000 на каждый, от 0 до 9 , распеделение равномерно, за исключением , но вполне yeah.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.