Pages: [1]   Go Down
Author Topic: random int not long?? help appreciated  (Read 1888 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi everyone  yet another question haha smiley-razz  

ok sh when you do a eg:

Code:
Serial.println(random(100000000, 999999999));

i get an output like(im using randomseed in the setup btw):

Code:
100014190
100015095
100018554
100023236
100004893
100004297
100003548
100031779
100029752
100006162
100023813
100029914
100012502
100028386
100021643
100001407
100023755
100008466
100015325
100024320
100002781
100022222
100010656
100020318
100023525
100009803
100009635
100007011
100004047
100007227
100002938
100007327
100004194
100009321
100008931
100007602
100005747
100029643
100017968
100012811
100007210
100011294
100001836
100028688
100020796

so im wanting it to have a bigger random but only the first 5 digits randomise and never over 32767 so i figured that the random() call is only an int  but i need it to be a long  or even better up to a unsigned long so i can get a nice lot of randomness rite up to 4,294,967,295  (unsigned long max number)

if someone can tell me how to do this that would be great, if its a microcontroller thing or software thing please tell me i would quite like to know why this happens.

cheers

callum
« Last Edit: May 26, 2008, 04:55:37 am by dustybike » Logged

Las Vegas, NV
Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The simplest thing I can think of: generate your random unsigned long by making two calls to random(), the first of which gives you your two low bytes and the second of which gives you your two high bytes.  Either that or you can google for random number generator algorithms and create your own implementation that isn't limited to two bytes (this probably wouldn't be very hard).

- Ben
Logged


0
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ah thank you ben   first to help once again  i appreciate it  ill look for the latter method.

if anyone knows the reason why it does it i would quite like to know  

cheers all
Logged

Las Vegas, NV
Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I did a little more digging and I think I can give you a more satisfying explanation.  I found the Arduino random functions in WMath.cpp:

Code:
long random(long howbig)
{
  long value;
  if (howbig == 0){
    return 0;
  }
  return rand() % howbig;
}

long random(long howsmall, long howbig)
{
  if(howsmall >= howbig){
    return howsmall;
  }
  long diff = howbig - howsmall;
  return random(diff) + howsmall;
}

These use the rand() function defined in stdlib.h, and rand() returns a signed int.  So what this means is that random() will return a number that is always less than or equal to 0x7FFF, even though the definition makes it seem like it can handle longs.  This would seem to be a bug in the implementation of random().  If you then look at what this means for random(howsmall, howbig), you see that you are returning a random signed int plus howsmall, which can be a long.  The result is exactly what you have already observed.

I think either the random functions should be rewritten to take arguments that are ints, or they should be implemented in a way that actually returns random longs.


- Ben
Logged


0
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thankyou very much ben i appreciate it so much    its nice to know it wasnt my fault  smiley   can i post that into the sugestions forum  or you can of course   jus tell me

cheers mate

callum
Logged

Las Vegas, NV
Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I just posted something there with a proposed fix.  Hopefully I thought it through well enough and didn't neglect some crucially important detail.

- Ben
Logged


New Zealand
Offline Offline
God Member
*****
Karma: 0
Posts: 999
Arduino pebbles
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Hopefully I thought it through well enough and didn't neglect some crucially important detail.
Heh, nothing like learning from others' mistakes... :-) *cough*debian*cough*

--Phil.
« Last Edit: May 26, 2008, 05:54:25 am by follower » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hay ben any chance u could pop up that file uv changed?   ill give it a right old test hehe

cheers

callum
Logged

Las Vegas, NV
Offline Offline
God Member
*****
Karma: 0
Posts: 507
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The simplest thing for you to do would probably be to make the change in your own arduino-0011 distribution.  The file in question is:

arduino-0011/hardware/cores/arduino/WMath.cpp

I suggest you make a backup of the file, and then try changing the random() function as I mentioned in my Bugs & Suggestions thread.  If you test it out, please let me know how it works.


- Ben
Logged


0
Offline Offline
Full Member
***
Karma: 0
Posts: 116
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The built in random function for any particular language is rarely very random or particularly useful for more than simple uses. The textbook example is using random numbers to calculate pi. It only works if the numbers are reasonably random and have a large range.

You can implement a much better random number generator with a few lines of code. It's on my to do list to dig up the one I wrote in college and port it to the Arduino.

I think I found it. Here it is in a form that might run on the Arduino, but it's untested.
Code:
unsigned long gXOld; // last random value

InitRealRandom()
{
      gXOld = millis();
}

double RandomNumber()
{
      unsigned long      temp;
                  
      temp = 663608941*gXOld;
      gXOld = temp;
      return(((double)temp)/((double)4294967295));
}
Logged

Pages: [1]   Go Up
Jump to: