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.
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...
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.
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!
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.
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:
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?
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.
@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):
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():
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?
@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.
I'm not really familiar with how the arduino environment generates it's random numbers. However, if it's using openssl then there is a bug in Debian (and its derivatives e.g. Ubuntu) that may be the cause.
The latter gives the version numbers of fixed packages for openssl by distro version (e.g. Hardy). It also mentions that Intrepid (8.10) had this bug while it was under development.
Tonight I'll check what version of openssl my Ubuntu 8.10 install is using. However, since my ISP currently has connectivity issues (submarine cable fault), I may not be able to post my results until I get back to work on Monday.
Veronica, it's a similar concept, but I would be very surprised if OpenSSL used the libc implementation of rand(). When you get into cryptography, people really get extremely picky at the mathematical features of their random-number-generators.
If this were put into a car analogy, the OpenSSL guys are complaining that the tires have a weak tread pattern that might have trouble on ice, while the Arduino behavior seen above is like noticing that you have three flat tires and no engine.
hmm, that makes sense halley, but it does seem, so far, as if its limited to debian distros maybe even just Ubuntu. Saxdude doesn't have the problem using SUSE 64 bit, whereas Berg (Kubuntu 8.10 32 bit) and I (Ubuntu 8.10 64 bit) do.
I don't have another linux distro to test on though I will try installing a vm with Centos to see if the problem still occurs.