Skip to main content
GameDev.net gamedev.net
🔒 Locked

Random Number

Started by Austrian Coder Mar 1, 2003 at 10:49 AM 3 replies 150+ views
Original Post
Austrian Coder
Austrian Coder
Hi! I am using this: int GetRanNum(int from, int to) { return (rand() % to) + from; } But this returns sometimes a number bigger than to, the max number. In the main function I call this: srand (time(NULL)); So where is here the problem? Thanks, Christian
Austrian Coder
Austrian Coder
I have fixed it now:

int GetRanNum(int von, int bis)
{
return rand() % (bis + 1 - von) + von;
}
Beelzebub
Beelzebub
try this is instead...


  
int GetRanNum(int from, int to)
{
return (rand() % (to-from)) + from; // wont return a value of ''to'' ever

// return (rand() % ((to-from)+1)) + from; // will return ''to''

}


but a solution giving a better spread of numbers is


  
#define RAND(__range) ((((long)rand ()) * (__range)) / (RAND_MAX+1))


and you''d use RAND((to-from)+1)+from
dorix
dorix
quote:
Original post by Beelzebub
try this is instead...
  
int GetRanNum(int from, int to)
{
return (rand() % (to-from)) + from; // wont return a value of 'to' ever
// return (rand() % ((to-from)+1)) + from; // will return 'to'
}

but a solution giving a better spread of numbers is

#define RAND(__range) ((((long)rand ()) * (__range)) / (RAND_MAX+1))


and you'd use RAND((to-from)+1)+from


How does that give a better spread of numbers? That will give you the same distribution you'll get from the original method. It has a few errors as well:

1. RAND_MAX on some systems is (2^31)-1. As soon as you add 1 to that, with signed integers, that RAND_MAX+1 you're dividing by becomes negative. Not what you wanted.
2. Use float (or double) casts in your macro to prevent LARGE_NUMBER/LARGER_NUMBER=0 precision errors.
#define RAND(__range) ((((float)rand()) * (float)(__range)) / (float)(RAND_MAX))   


To the OP, there's a situation where your second version of the original function will not behave as you anticipated:
GetRanNum(10, 5);   

To fix that, in the body of your GetRanNum function, use minimum and maximum macros to ensure that what you expect to be "from" is the smaller number, and what you expect to be "to" is the larger number.

Cheers, dorix

edit: Okay, I can see how Beelzebub's method will provide a better random distribution -- using modulo (%) only uses the lower order bits, which may be nowhere near as random as higher order bits on older systems. My apologies.

[edited by - dorix on March 1, 2003 1:07:37 PM]

[edited by - dorix on March 1, 2003 2:59:19 PM]
Beelzebub
Beelzebub
quote:
edit: Okay, I can see how Beelzebub''s method will provide a better random distribution -- using modulo (%) only uses the lower order bits, which may be nowhere near as random as higher order bits on older systems. My apologies.


Just to emphasise the differences between the modulo method and mine... Suppose rand() returned the following sequence of numbers 0,16,32,48,64.... impossible I know, but this is just to emphases the point.
Using the modulo method, RAND(4096) would return 0 for ALL of my specified return values.
Using my method you would get 0,2,4,6,8 - a much better spread of values.

quote:

1. RAND_MAX on some systems is (2^31)-1. As soon as you add 1 to that, with signed integers, that RAND_MAX+1 you''re dividing by becomes negative. Not what you wanted.
2. Use float (or double) casts in your macro to prevent LARGE_NUMBER/LARGER_NUMBER=0 precision errors.


1. I agree, RAND_MAX could be defined as you say, which would give the error you describe, but my VC6.0 has it defined as 0x7fff which doesn''t cause a problem.
Casting to an unsigned long on 32-bit integer systems would probably be a more portable solution - providing int is defined as signed on your system.
2. Yep I agree use doubles/floats, my code comes from when intel C compilers were 16-bit, and floating point maths token several hundred cycles to execute.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.