Page 2 of 3
Re: NXC random numbers / random seed
Posted: 29 Jan 2011, 18:34
by HaWe
fine, thank you, this seems to work :)
Code: Select all
// global variable to plant the random seed
unsigned int RAND_SEED = 1; // to be patched, e.g. by srand()
// random function, only positive values
unsigned int rand_()
{
RAND_SEED = RAND_SEED * 1103515245 + 12345;
return (RAND_SEED % (RAND_MAX + 1));
}
// random seed for a new random series
void srand(int seed)
{
RAND_SEED = seed; // just patches the global RAND_SEED variable
}
//******************************************************
task main(){
int myRandomNumber;
srand(1); // or any other value, e.g. a timer counter
while (true) {
myRandomNumber=rand_() % 100; // 0...99
printf("%d", myRandomNumber);
Wait(1000);
}
}
I will include this into my math.h!
:D
Re: NXC random numbers / random seed
Posted: 29 Jan 2011, 19:47
by HaWe
I'm curious if it would be probably better to use "long" instead of "int" for the rand_ argument because it multiplies by 1103515245:
Code: Select all
00038 int rand_r(unsigned int *seed)
00039 {
00040 *seed = *seed * 1103515245 + 12345;
00041 return (*seed % ((unsigned int)RAND_MAX + 1));
00042 }
edit: I assume this is for 32bit systems where they have 32bit ints, not 16bit ints=shorts what actually is what we have...
Code: Select all
unsigned long RAND_SEED = 1;
//...
unsigned int rand_()
{
RAND_SEED = RAND_SEED * 1103515245 + 12345;
return (RAND_SEED % (RAND_MAX + 1));
}
Re: NXC random numbers / random seed
Posted: 29 Jan 2011, 22:37
by gloomyandy
Yes this will be for 32bit ints does NXC really have 16 bit ints? I'm surprised as the native word size for the ARM is 32bits...
Re: NXC random numbers / random seed
Posted: 29 Jan 2011, 22:53
by mattallen37
gloomyandy wrote:Yes this will be for 32bit ints does NXC really have 16 bit ints? I'm surprised as the native word size for the ARM is 32bits...
From the HTML NXC help file
In NXC the int type is a signed 16-bit value.
Also from the same help file.
In NXC the long type is a signed 32-bit value.
So it appears that NXC supports 16 bit signed variables as "int", but there are other variable options (such as unsigned).
Re: NXC random numbers / random seed
Posted: 29 Jan 2011, 23:15
by HaWe
I wrote a litte program with which you may observe the distibution of the random numbers.
The numbers are randomized from 0...15 and their distribution is displayed on the screen over the time.
You may freeze the screen pressing any button (ExitBtn not too long!) ;)
Enjoy it!
Code: Select all
//*****************************************************************
// math.h random functions
// global variable to plant the random seed
unsigned long RAND_SEED = 1; // to be patched, e.g. by srand()
// random function, only positive values
unsigned int rand_()
{
RAND_SEED = RAND_SEED * 1103515245 + 12345;
return (RAND_SEED % (RAND_MAX + 1));
}
// random seed for a new random series
void srand(int seed)
{
RAND_SEED = seed; // just patches the global RAND_SEED variable
}
//*****************************************************************
// nxtio.h string and i/o functions
#define printf1( _x, _y, _format1, _value1) { \
string sval1 = FormatNum(_format1, _value1); \
TextOut(_x, _y, sval1); \
}
bool btnhit(){
return ( ButtonPressed(BTN1, false) || ButtonPressed(BTN2, false)
|| ButtonPressed(BTN3, false) || ButtonPressed(BTN4, false));
}
char LCDline[]={56,48,40,32,24,16,8,0};
//*****************************************************************
task main(){
int myRand, ibuf, x, y;
int RandDistr[16];
SetLongAbort(1);
srand(1);
// or any other value, e.g. using a timer counter like
srand(CurrentTick()*BatteryLevel());
printf1( 0,LCDline[0],"seed=%d",RAND_SEED);
printf1( 0,LCDline[3],"%s", "press any btn");
while(!btnhit());
ClearScreen();
for (char i=0; i<8; i++) {
printf1( 0,LCDline[i],"%2d",2*i);
printf1(46,LCDline[i],"|%2d",2*i+1);
}
while (RandDistr[myRand]<9999) {
myRand=rand_() % 16; // 0...15
RandDistr[myRand]++;
ibuf=RandDistr[myRand];
x=(myRand%2)*50;
y=myRand/2;
printf1(22+x,LCDline[y],"%4d",ibuf);
while(btnhit()); // wait while button pressed for screen freezing
}
while(true);
}
Re: NXC random numbers / random seed
Posted: 30 Jan 2011, 02:10
by m-goldberg
doc-helmut wrote:But if I understand you correctly, we will get at least ALWAYS an independent series of random numbers and NEVER identical series....(?)
Yes, you will always get a different sequence of pseudo-random numbers from NXC since srand is continuously being called with the current system time. There is, I suppose, a vanishing small probability the you could get the same sequence by reseting the system clock (by turning the NXT off and then on again) but you certainly couldn't depend on it
Re: NXC random numbers / random seed
Posted: 30 Jan 2011, 09:29
by HaWe
thanks a lot, Morton and Andy,
that led me to the idea to use
Code: Select all
srand( CurrentTick()*BatteryLevel() )
to be a kind of "real randomized initializaion seed" to get "real independent random sequences".
And if you want to have always identical sequences for test purposes you can use
or whatever.
I changed the code above, so you may see now how the seed looks like before the randomization starts!
What do you think of that, peeps? ;)
(on the highway to ACDC... :P )
Re: NXC random numbers / random seed
Posted: 31 Jan 2011, 21:09
by afanofosc
I was not clear in my email to Morton regarding how the firmware initializes the random seed - or more precisely, how the RandomNumber system call function works. The way the firmware works is that each time you ask for a random number via the RandomNumber system call it increments a counter. When that counter reaches 20 it is set back to 0. If the counter value is 0 then it calls srand before it calls rand. I could change this, of course, and make it so that you can call srand directly in a user program but I am not sure why I would want to take the time to do that. I guess if you wanted to generate the same random numbers each time you run your program then you would want to be able to control the seed and how frequently srand is called.
John Hansen
Re: NXC random numbers / random seed
Posted: 31 Jan 2011, 21:40
by HaWe
Andy's C code random algorithm which I'm using in my code above seems to do quite that:
I can plant both constant or varying seeds to get identical or varying random sequences.
I'm not quite sure if the generated "random" sequences of Andy's code are all stochastical independend. The distribution of single drawings seems to be normal distributed, but it has to be proved that all subsequences are uniformly distributed (for n -> ∞). Maybe for a first test I once will try a Chi-square test of all 16x16 number couples if I'll find the time...
I think for the moment Andy's algorithm for "my" rand_() and srand() is a good workaround for a substitute for the Lego Firmware spoof rand function ;)
Re: NXC random numbers / random seed
Posted: 01 Feb 2011, 16:20
by HaWe
just got a hint to the Mersenne-Twister "TT800": That might be an alternative random algorithm:
Code: Select all
unsigned TT800(void) {
const int N = 25;
const int M = 7;
const unsigned A[2] = { 0, 0x8ebfd028 };
static unsigned y[25];
static int index = N+1;
if (index >= N) {
int k;
if (index > N) {
unsigned r = 9, s = 3402;
for (k=0 ; k<N ; ++k) {
r = 509845221 * r + 3;
s *= s + 1;
y[k] = s + (r >> 10);
}
}
for (k=0 ; k<N-M ; ++k)
y[k] = y[k+M] ^ (y[k] >> 1) ^ A[y[k] & 1];
for (; k<N ; ++k)
y[k] = y[k+(M-N)] ^ (y[k] >> 1) ^ A[y[k] & 1];
index = 0;
}
unsigned e = y[index++];
e ^= (e << 7) & 0x2b5b2500;
e ^= (e << 15) & 0xdb8b0000;
e ^= (e >> 16);
return e;
}