Go Down

Topic: Help - Random function not working (Read 6 times) previous topic - next topic

Patzak

Hi...Just received an Arduino Duemilanove...works fine with everything that I have tried with the exception of all the random functions.  The random calls all return one of two values when placed in a loop, I am just trying to randomly flash five LEDs.  Random(1,6) returns 2 or 4.  Loaded example from language reference and experienced a similar problem.  Any help will be appreciated.

Thank You,
Pat

RIDDICK

#1
Nov 20, 2008, 11:42 pm Last Edit: Nov 20, 2008, 11:43 pm by RIDDICK Reason: 1
Hi!

What if u use
random(0,5120)/1024+1
instead of
random(1,6)
?
This would use some upper bits of the random numbers... The lower bits r sometimes not really random... *giggle*  ;)

Do u call random() just once between two board-resets?

do u call
randomSeed(analogRead(0));
or so, too?

random() uses GNU CC's rand() function, which should deliver quite good pseudo-random numbers...

Bye
-Arne

mikalhart

#2
Nov 20, 2008, 11:53 pm Last Edit: Nov 20, 2008, 11:54 pm by mikalhart Reason: 1
There is a known bug with the current Arduino implementation of random(x) and random(x, y).  As a replacement, try the following:

Code: [Select]
unsigned long newrandom(unsigned long howsmall, unsigned long howbig)
{
 return howsmall + random() % (howbig - howsmall);
}


(This calls the stdlib implementation of random.)

Mikal

mikalhart

Patzak--

I think you must be seeing something different than me.  When I repeatedly call (the built in Arduino) random(1, 6), I get perfectly reasonable values:

2 1 1 4 1 2 1 5 3 2 4 4 1 2 2 2 5 4 3 1 2 2 1 3 1 2 4 1 5 2 1 5 1 2 2 3 4 3 5 4 2 5 4 3 1 1 5 1 4 2 3 1 5 4 5 1 1 5 1 3 4 2 2 5 4 2 3 5 1 5 4 3 5 5 3 3 5 5 3 5 5 2 5 4 4 2 5 3 1 2 2 1 2 5 2 2 3 4 4 3

This was generated with
Code: [Select]
 for (int i=0; i<100; ++i)
 {
   Serial.print(random(1, 6));
   Serial.print(" ");
 }


Mikal

Patzak

I purchased a windows Vista laptop today.  Loaded Arduino-0012  and ran the same random() code.  All results were acceptable.  There is a bug in Linux AMD_64  for all random functions.

mikalhart

That's distressing.  It's hard to see how that can be; isn't it the same compiler?  Does anyone else using AMD_64 Arduino experience that?

Mikal

Berg

Doesn't work for me either.
Duemilanove, Arduino 0012 Alpha, Linux (Kubuntu 8.10) x86, Intel CPU).

Default random w/o randomSeed(analogRead(0));
Code: [Select]

long randomred = random(127);
long randomgreen = random(250);
long randomblue = random(250);
Serial.print(randomblue);
Serial.print(" ");
Serial.print(randomgreen);
Serial.print(" ");
Serial.println(randomblue);

Produces

38 236 38
236 238 236
238 38 238
38 38 38
38 236 38
236 238 236
238 38 238
38 38 38
38 236 38

With randomSeed(analogRead(0));
I get

38 236 38
236 238 236
238 38 238
38 38 38
38 236 38
236 238 236
238 38 238
38 38 38


Same results every time, no matter how many restarts/reboots/plugging things in on pin 0.

Using Mikalhart's suggestion:
Code: [Select]
long randomred = newrandom(0,127);
long randomgreen = newrandom(0,250);
long randomblue = random(0,250);
Serial.print(randomblue);
Serial.print(" ");
Serial.print(randomgreen);
Serial.print(" ");
Serial.println(randomblue);

Produces

236 0 236
38 210 38
38 160 38
238 34 238
236 0 236
38 210 38
38 160 38
238 34 238
236 0 236
38 210 38


Is this a bug or am I missing something?

mikalhart

Well, one minor observation is that you are printing randomblue twice and randomred not at all, but that doesn't explain the remarkably unrandom behavior.  Yipes!

Mikal

Berg

Quote
Well, one minor observation is that you are printing randomblue twice and randomred not at all


Ooops.  :-[
Well, after rewriting the code a number of times, trying  to find what I was certain was an error on my behalf, I guess another error snuck in.

However, I am now more or less certain that there is a bug in the Linux version of Arduino: I ran the very same code on a Windows XP computer, and it gave me random numbers without the above repetitions.

Where would I file a bug report about this?

mikalhart

Quote
However, I am now more or less certain that there is a bug in the Linux version of Arduino.

I unhappily agree.  Let's see if we can get to the bottom of this.  Would anyone who wants to participate, please run this short sketch:

void setup()
{
 Serial.begin(9600);
 for (int i=0; i<20; ++i)
 {
   long l = random();
   Serial.print(l); Serial.print(" ");
   Serial.print(l % 6); Serial.print(" ");
   Serial.print(l % 127); Serial.print(" ");
   Serial.pri lnt(l % 250); Serial.println();
 }
}

void loop()
{}

If your results differ from those posted by anyone else, please note the platform and post them.  When I run this with Arduino 0012 from my Vista laptop, I get the following:

Code: [Select]

16807 1 43 57
282475249 1 71 249
1622650073 5 29 73
984943658 2 111 158
1144108930 4 93 180
470211272 2 122 22
101027544 0 60 44
1457850878 2 98 128
1458777923 5 43 173
2007237709 1 42 209
823564440 0 47 190
1115438165 5 86 165
1784484492 0 126 242
74243042 2 112 42
114807987 3 114 237
1137522503 5 13 3
1441282327 1 94 77
16531729 1 12 229
823378840 4 121 90
143542612 4 100 112


I would expect the Linux users to report something quite different.

Mikal

Veronica

Hi,

Good thing I searched the forum before posting my first question :) I've got the same problem of repeating numbers.

Results from Ubuntu 8.10 x86_64 and arduino 0012

0 0 0 0
31031784 0 96 34
26852320 4 75 70
4242000 0 73 0
842292 0 28 42
453960 0 62 210
211932 0 96 182
84160 4 86 160
0 0 0 0
31031784 0 96 34
26852320 4 75 70
4242000 0 73 0
842292 0 28 42
453960 0 62 210
211932 0 96 182
84160 4 86 160
0 0 0 0
31031784 0 96 34
26852320 4 75 70
4242000 0 73 0


Ver.

mikalhart

Wow, that's really a stunning bug.  And the scary thing is, it's nothing (apparently) to do with Arduino, since my test sketch calls the stdlib implementation of random().

Thanks, Veronica.  Does anyone else get anything different?  Do all Linux implementations get the same results?

Mikal

halley

#12
Dec 16, 2008, 05:25 am Last Edit: Dec 16, 2008, 05:32 am by halley Reason: 1
I would not be surprised if it was simply an artifact of the 8 bit processing?  As much as I'm impressed that the cross compiler is able to do all sorts of amazing math accurately, I also know that PRNG routines are generally bit-fiddling exercises more than actual math.  Some unexpected endian-ness bug could easily blow the seed series.

I wonder if the Mersenne Twister (the current darling of PRNG science) is implementable instead of the stdlib variety.  I recall reading that it actually is less computationally intense than some, but may require more scratch memory.

OSX Arduino 0012, Duemilanove:

Code: [Select]
16807 1 43 57
282475249 1 71 249
1622650073 5 29 73
984943658 2 111 158
1144108930 4 93 180
470211272 2 122 22
101027544 0 60 44
1457850878 2 98 128
1458777923 5 43 173
2007237709 1 42 209
823564440 0 47 190
1115438165 5 86 165
1784484492 0 126 242
74243042 2 112 42
114807987 3 114 237
1137522503 5 13 3
1441282327 1 94 77
16531729 1 12 229
823378840 4 121 90
143542612 4 100 112


Looks good here, I guess.  What is different between OSX backends and Ubuntu backends, for the avr-gcc cross-compiled stdlib?

mikalhart

#13
Dec 16, 2008, 05:49 am Last Edit: Dec 16, 2008, 06:07 am by mikalhart Reason: 1
@halley: What 8 bit processing are you talking about?  All the small modulus operations?  I just threw those in because people earlier in the thread were noticing unpleasant patterns with those.  They're superflous as it turns out, because the real unpleasant pattern is the series of raw numbers returned by the stdlib random() function itself (in Linux):

0(!), 31031784, 26852320, 4242000, 842292, 453960, 211932, 84160, 0(!!), 31031784, ...

It appears that there are only 8 "random" numbers before the series repeats!  Something is badly wrong.  Here is the source to avr-libc 1.6.2's random():

Code: [Select]
static long
do_random(unsigned long *ctx)
{
 /*
  * Compute x = (7^5 * x) mod (2^31 - 1)
  * wihout overflowing 31 bits:
  *      (2^31 - 1) = 127773 * (7^5) + 2836
  * From "Random number generators: good ones are hard to find",
  * Park and Miller, Communications of the ACM, vol. 31, no. 10,
  * October 1988, p. 1195.
  */
 long hi, lo, x;
 x = *ctx;
 /* Can't be initialized with 0, so use another value. */
 if (x == 0)
   x = 123459876L;
 hi = x / 127773L;
 lo = x % 127773L;
 x = 16807L * lo - 2836L * hi;
 if (x < 0)
   x += 0x7fffffffL;
 return ((*ctx = x) % ((unsigned long)RANDOM_MAX + 1));
}

long
random_r(unsigned long *ctx)
{
 return do_random(ctx);
}

static unsigned long next = 1;

long
random(void)
{
 return do_random(&next);
}

void
srandom(unsigned long seed)
{
 next = seed;
}


As you can see, assuming you don't call srandom(), the first random number generated should be 16807, which it is in both yours and my sequences.  Why not Linux as well?

Mikal

EDIT: Is there anyone using 32-bit Linux experiencing this problem?

halley

#14
Dec 16, 2008, 06:37 am Last Edit: Dec 16, 2008, 06:37 am by halley Reason: 1
@mikalhart, I meant the 8bit architecture of the atmega-- some bug in the avr tools.  Maybe doing huge number modulus operations is not well-tested and the mini-routine for doing it has a bug in one particular release of the libs.  Maybe the use of a static long does not put the right value in PROM or RAM on startup.  I just looked at the elf disassembly for the code you showed, and it *looks* okay but I am not used to avr opcodes enough to spot bugs.

Go Up