News:

As usual while waiting for the next release - don't forget to check the nightly builds in the forum.

Main Menu

random function question

Started by Deamon, April 03, 2006, 11:33:06 PM

Previous topic - Next topic

Deamon

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

#1
C version:
Code (cpp) Select

#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) Select

#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.

TDragon

In addition to Takeshi's helpful post (neither of your samples will compile, Takeshi :?), allow me to add this:

Code (cpp) Select

#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.
[url="https://jmeubank.github.io/tdm-gcc/"]https://jmeubank.github.io/tdm-gcc/[/url] - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

takeshimiya

Quote from: TDragon on April 04, 2006, 12:21:27 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?

TDragon

Because it didn't #include <ctime> at the time I made my post.
[url="https://jmeubank.github.io/tdm-gcc/"]https://jmeubank.github.io/tdm-gcc/[/url] - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

takeshimiya

Quote from: TDragon on April 04, 2006, 12:42:12 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

TDragon

My apologies; your original C++ sample does indeed compile under MinGW32/GCC (assuming one adds a wrapping main function).
[url="https://jmeubank.github.io/tdm-gcc/"]https://jmeubank.github.io/tdm-gcc/[/url] - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

takeshimiya

Quote from: TDragon 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).

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

Code (cpp) Select

#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

Quote from: TDragon on April 04, 2006, 12:21:27 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 ?

QuoteThere'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

TDragon

Quote from: Deamon on April 04, 2006, 01:54:41 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
QuoteThere'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. :)
[url="https://jmeubank.github.io/tdm-gcc/"]https://jmeubank.github.io/tdm-gcc/[/url] - TDM-GCC compiler suite for Windows (GCC 9.2.0 2020-03-08, 32/64-bit, no extra DLLs)

Deamon

#10
Quote from: TDragon on April 04, 2006, 02:55:37 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

Ceniza

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 :)

thomas

Quote from: Deamon on April 04, 2006, 05:54:15 AM
QuoteThat'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."

me22

Quote from: Takeshi Miya on April 04, 2006, 01:28:46 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:
#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:
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

Quote from: me22 on April 05, 2006, 05:43:52 AM
Quote from: Takeshi Miya on April 04, 2006, 01:28:46 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.