Я дал рабочий пример (с учётом поправки, сначала по ошибке написал 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, но и этого достаточно.