Author Topic: random function question  (Read 50860 times)

Deamon

  • Guest
random function question
« on: April 03, 2006, 11:33:06 pm »
Hi folks,

under Borland i used the:

randomize();
random(9);

to get a random value betwin 0 and 9 but when i try to compile it under WingW i realize again that it's not ansi compliant. Now my question is how can i achieve the same results in an ansi compliant way ?

regards,
Deamon

takeshimiya

  • Guest
Re: random function question
« Reply #1 on: April 03, 2006, 11:36:48 pm »
C version:
Code: cpp
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

srand(time(NULL));
int i;
for(i = 0; i < 10; i++)
    printf("Random number #%d: %d\n", i, rand());

C++ version:
Code: cpp
#include <cstdlib>
#include <iostream>
#include <ctime>

std::srand(std::time(0));
for(int i = 0; i < 10; i++)
    std::cout << "Random number #" << i << ": " << std::rand() << std::endl;

The function srand() is used to seed the random sequence generated by rand(). For any given seed, rand() will generate a specific "random" sequence over and over again.
« Last Edit: April 04, 2006, 12:29:54 am by Takeshi Miya »

Offline TDragon

  • Lives here!
  • ****
  • Posts: 943
    • TDM-GCC
Re: random function question
« Reply #2 on: April 04, 2006, 12:21:27 am »
In addition to Takeshi's helpful post (neither of your samples will compile, Takeshi :?), allow me to add this:

Code: cpp
#include <stdlib.h> // if using C++, #include <cstdlib>; may not be necessary in C
#include <time.h> // if using C++, #include <ctime>

// Seed the RNG
srand(time(0));

int RandomIntInRange(int low, int high)
{
return (int)(rand() / (RAND_MAX / (double)(high - low))) + low;
}

There's probably an unnecessary cast in there, but don't disparage my parentheses -- I use them to indicate my thought processes when I come back to the code a few years down the road.
https://jmeubank.github.io/tdm-gcc/ - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

takeshimiya

  • Guest
Re: random function question
« Reply #3 on: April 04, 2006, 12:31:42 am »
In addition to Takeshi's helpful post (neither of your samples will compile, Takeshi :?)

Sorry, forgot to add #include <time.h> for the first example.
The second example compiles fine, why do you say it'll not compile?

Offline TDragon

  • Lives here!
  • ****
  • Posts: 943
    • TDM-GCC
Re: random function question
« Reply #4 on: April 04, 2006, 12:42:12 am »
Because it didn't #include <ctime> at the time I made my post.
https://jmeubank.github.io/tdm-gcc/ - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

takeshimiya

  • Guest
Re: random function question
« Reply #5 on: April 04, 2006, 12:46:16 am »
Because it didn't #include <ctime> at the time I made my post.
Yup, those things happens. However, it *did* compiled fine in g++.
Somehow, the stdlib++ includes somewhere the function time(), which maked it compile and run fine. :P

Offline TDragon

  • Lives here!
  • ****
  • Posts: 943
    • TDM-GCC
Re: random function question
« Reply #6 on: April 04, 2006, 12:50:55 am »
My apologies; your original C++ sample does indeed compile under MinGW32/GCC (assuming one adds a wrapping main function).
https://jmeubank.github.io/tdm-gcc/ - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

takeshimiya

  • Guest
Re: random function question
« Reply #7 on: April 04, 2006, 01:28:46 am »
My apologies; your original C++ sample does indeed compile under MinGW32/GCC (assuming one adds a wrapping main function).

BTW, I'm very surprised that this compiles fine with no warnings under MinGW32/G++ (compiled with -Wall -W -pedantic):

Code: cpp
#include <iostream>

int main()
{
srand(time(0));
for(int i = 0; i < 10; i++)
    printf("Random number #%d: %d\n", i, rand());
}

stdlib++'s <iostream> is doing nasty things here. :shock:

Notice how srand(), rand(), and printf(), works without having to include <cstdlib>.
And <iostream> internally must be including <stdlib.h> instead of <cstdlib>, because notice how putting std:: qualifier is not requiered.

Also notice how including <ctime> was not requiered, neither qualifying time() with std::.

Deamon

  • Guest
Re: random function question
« Reply #8 on: April 04, 2006, 01:54:41 am »
#include <stdlib.h> // if using C++, #include <cstdlib>; may not be necessary in C
#include <time.h> // if using C++, #include <ctime>

// Seed the RNG
srand(time(0));

int RandomIntInRange(int low, int high)
{
   return (int)(rand() / (RAND_MAX / (double)(high - low))) + low;
}

Are you sire about it ?

When i compile it it tells me:

main.cpp:20: ISO C++ forbids declaration of `srand' with no type
main.cpp:20: `int srand' redeclared as different kind of symbol
D:/Programme/CodeBlocks/share/CodeBlocks/plugins/compilers/MinGW/include/stdlib.h:362: previous
   declaration of `void srand(unsigned int)'
Process terminated with status 1 (0 minutes, 3 seconds)

When i put it inside RandomIntInRange() or main then it works but why doesn't it work globaly ?

And TDragon, is see you made your own function for random number with a range resolution! Does that mean there is now specialized function for it in the ansi libs ?

Quote
There's probably an unnecessary cast in there, but don't disparage my parentheses -- I use them to indicate my thought processes when I come back to the code a few years down the road.

What ?

regards,
Deamon

Offline TDragon

  • Lives here!
  • ****
  • Posts: 943
    • TDM-GCC
Re: random function question
« Reply #9 on: April 04, 2006, 02:55:37 am »
When i compile it it tells me:

main.cpp:20: ISO C++ forbids declaration of `srand' with no type
main.cpp:20: `int srand' redeclared as different kind of symbol
D:/Programme/CodeBlocks/share/CodeBlocks/plugins/compilers/MinGW/include/stdlib.h:362: previous
   declaration of `void srand(unsigned int)'
Process terminated with status 1 (0 minutes, 3 seconds)

When i put it inside RandomIntInRange() or main then it works but why doesn't it work globaly ?
srand(time(0)); is a function call. Function calls must be inside other functions or used as expressions -- they don't qualify as statements in the global scope. You should place it in your main function or initialization function (if you have one).

Quote
And TDragon, is see you made your own function for random number with a range resolution! Does that mean there is now specialized function for it in the ansi libs ?
That's correct, there is no function in ANSI C that returns a random number within a custom range.

Quote
Quote
There's probably an unnecessary cast in there, but don't disparage my parentheses -- I use them to indicate my thought processes when I come back to the code a few years down the road.
What ?
Nothing. :)
https://jmeubank.github.io/tdm-gcc/ - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

Deamon

  • Guest
Re: random function question
« Reply #10 on: April 04, 2006, 05:54:15 am »
srand(time(0)); is a function call. Function calls must be inside other functions or used as expressions -- they don't qualify as statements in the global scope.


Oh yeah forgot that we are talking about a function call here LOL

I guess it's late here again :)

Quote
That's correct, there is no function in ANSI C that returns a random number within a custom range.

Bump! That sucks. Man i love the borland guys. They make such usefull stuff. The ansi guys feel the same:

http://tigcc.ticalc.org/doc/stdlib.html#random

And thanks for the help guys. Searched the net and found everything just not what i needed. What is not a miracle cose as you told me there is no specialized function for it. LOL

regards,
Deamon
« Last Edit: April 04, 2006, 05:56:32 am by Deamon »

Offline Ceniza

  • Developer
  • Lives here!
  • *****
  • Posts: 1441
    • CenizaSOFT
Re: random function question
« Reply #11 on: April 04, 2006, 04:23:56 pm »
I still wonder why you posted that link to the gcc port for Texas Instruments calcs...

What's so true is how ppl get used to those extra functions provided by Borland :)

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: random function question
« Reply #12 on: April 04, 2006, 07:30:20 pm »
Quote
That's correct, there is no function in ANSI C that returns a random number within a custom range.

Bump! That sucks. Man i love the borland guys. They make such usefull stuff.
Actually that doesn't suck at all. You can write your own trivial wrapper function which fits your needs exactly. It may be arbitrarily precise (like the above one) or abitrarily efficient (like for example using & if you need a less-than-some-power-of-two random).

For example, the above function is guaranteed to return a good random distribution. However, other solutions are possible which are on the order of 2-10 times faster but which might not have the same statistical properties (rand % a + b will for example be about twice as fast, and a construct using & instead of % might be 10-20 times as fast).

For applications which require a good random distribution, using % and & was an extremely bad idea back in the old days (1970-2000), as in the good old standard C generator the lower bits were not random at all (and % isn't either, if you are pedantic)!
Practically every rand() implementation uses MT these days, and most applications don't need perfect distributions, so that is fine either way... :)

If you use whatever the Borland guys made up, then you are bound to whatever they decided was right. This may not be what you want.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline me22

  • Official tester
  • Multiple posting newcomer
  • ***
  • Posts: 53
    • TA Universe
Re: random function question
« Reply #13 on: April 05, 2006, 05:43:52 am »
stdlib++'s <iostream> is doing nasty things here. :shock:

Actually, C++ headers are allowed to include as many or as few other C++ headers as they like, so it's perfectly acceptable for it to do that.  This is the reason why using namespace std; is dangerous (since you have no idea which headers are being brought into scope) and why you are supposed to include the headers declaring anything you use, since you can't even ( technically ) rely on <iostream> including <istream> and <ostream>.

As for the original point of this thread:
Code
#include <ctime>
#include <cstdlib>
void randomize() { std::srand( std::time(0) ); }
int random(int upper) { return std::rand()%(upper+1); }
( if you're using C, s/std:://g and s/<c(.+?)>/<$1.h>/g )

Note, however, that the % method of getting random numbers is actually a fairly bad pseudo-random with most crts.

The better way:
Code
double random() { std::rand()/(RAND_MAX+1.); }
then n*random() will give you a decently pseudo-random number in [0,n)

If you want really good (pseudo-)random numbers, then use http://www.boost.org/libs/random

takeshimiya

  • Guest
Re: random function question
« Reply #14 on: April 05, 2006, 06:05:24 am »
stdlib++'s <iostream> is doing nasty things here. :shock:

Actually, C++ headers are allowed to include as many or as few other C++ headers as they like, so it's perfectly acceptable for it to do that. 
It's probable that you didn't read the entire post.
The point is not that <iostream> is bringing to scope (to std::) some C++ headers, but the point is that it is bringing to scope C headers, therefore making really useless the whole C++ headers for std qualifiers (cstdlib, ctime, c*...), and also helping to write non-portable programs.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: random function question
« Reply #15 on: April 05, 2006, 09:35:41 am »
Quote
Note, however, that the % method of getting random numbers is actually a fairly bad pseudo-random with most crts.
Well, it depends. The reason why people say that it produces "bad" random numbers is that it changes the distribution (unless you use a factor of the input range). For example if you have an ideal PRNG with RAND_MAX == 10000 and you write rand() % 8000, then the numbers 0 to 1999 have a 2/10000 likelihood instead of 1/10000. That is a relative difference of 100%, but neglegible as an absolute difference.
It is really bad if you need an even distribution (as said above), but in many cases this does not really matter. Often you need a random number generator just to do something that is a bit queer and does not look deterministic at first glance. For that, modulus is just good enough.

However, the good thing is that % is by order of magnitude faster than converting from int to double and back plus two double divides. True, you could replace one division by a multiply, and the compiler might eleminate the other if the output range is a compile-time constant, but the double to int conversion remains, and it is is the biggest party pooper.

Bitwise & is even better if you can live with a pow2-1 range, since it does not change the distribution (so if the input is a "good random", then the output is a "good random"), and it only takes something like 2-3 CPU cycles.

It really depends on what you do. If you need 3 random numbers, then you would probably want them to have a good distribution. If you need 300,000,000 then you would probably want them to be evaluated as fast as possible.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."