Thread: random isn't really random?

  1. #16
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Salem gave a very useful link which advised to use high-order bits.

    Code:
    outcome=rand()%2; //this is bad
    .....
    outcome=(rand()&0x4000)>>14; //this is better
    Last edited by maxorator; 06-07-2008 at 08:54 AM.
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  2. #17
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thanks for the responses!

    Its really strange why it won't compile with srand().
    Anyway i solved the problem using only the time() and the wait() functions and im getting different results so its working.
    You can fiddle with the wait() value even more i guess.

    Code:
    #include <ctime>
    #include <iostream>
    #include <cstdlib>
    using namespace std;
    int flip(void);
    void wait ( double seconds )
    {
      clock_t endwait;
      endwait = clock () + seconds * CLOCKS_PER_SEC ;
      while (clock() < endwait) {}
    }
    
    int main()
    {
    	for(;;)
    	{
            	int headCount=0;
    	        int tailCount=0;
              for (int i=1; i<=10; i++)
        	  {
        		if (flip() == 0)
        		{
        			cout << " " << "H, ";
        			tailCount++;
        			flip();
        			wait(0.1);
                    }
                    else
                    { 
        			cout << " " << "T, ";
        			headCount++;
        			flip();
        			wait(0.5);
                    }
               }  
        	   cout << "\nHead " << headCount << endl;
        	   cout << "Tail " << tailCount << endl;
               system ("pause");
           }
           return 0;
    }
    int flip()
    {  
        int outcome;
        outcome = time(0) &#37; 2 ;
        return outcome;
    }
    Last edited by Ducky; 06-07-2008 at 09:26 AM.
    Using Windows 10 with Code Blocks and MingW.

  3. #18
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
      while (clock() < endwait) {}
    Do NOT do this.
    It will consume 100% of one processor core, just wasted on your pointless endless loop and steals cpu time from other applications.
    Use platform-specific sleep functions instead.
    For windows, it's Sleep (in milliseconds) and for Linux, it's sleep (in seconds, I believe).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #19
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Its really strange why it won't compile with srand().
    Have you read Drac's example?

    srand() doesn't return a value.
    srand() tells the pseudo random sequence where to start, rand() returns the next in the sequence with each successive call.

    From a given seed, all pseudo random generators always return the same sequence, no matter how many times you run the experiment, or how quickly you ask for the next one.

    > You can fiddle with the wait() value even more i guess.
    The wait() adds nothing, since most simple implementations of rand() pay no attention to time.
    Code:
    srand(10);
    for ( i = 0 ; i < 10 ; i++ ) printf("%d ", rand() );
    srand(10);
    for ( i = 0 ; i < 10 ; i++ ) {
        printf("%d ", rand() );
        wait(.5);
    }
    Will produce the same sequence.

    All it does it stop you from running the program twice in the same second, which srand( time(0) ); is vulnerable to.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #20
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thanks, i get it now.
    Using Windows 10 with Code Blocks and MingW.

  6. #21
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Maxorator your oparation gives always the same.
    With the modulus it changes at least, even if its a bit predictable, not much though.
    Try it if you dont believe me. I simplified the code.

    Code:
    #include <ctime>
    #include <iostream>
    #include <cstdlib>
    #include <windows.h>
    using namespace std;
    
    int x;
    
    int main()
    {
    	
    	for(;;)
    	{
        	    int headCount=0;
    	    int tailCount=0;
                 for (int i=1; i<=6; i++)
        	    {
                   Sleep(839);
                   srand(time(NULL));
    	        x =  rand() &#37;2;
             
        		if (x == 0)
        		{
        			cout << " T, ";
        			tailCount++;
                    }
                    else
                   { 
        			cout << " H, ";
        			headCount++;
                   }
            }
        	cout << "\nHead " << headCount << endl;
        	cout << "Tail "   << tailCount << endl;
            system ("pause");
        }
        return 0;
    }
    Last edited by Ducky; 06-07-2008 at 11:45 AM.
    Using Windows 10 with Code Blocks and MingW.

  7. #22
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Well maxorator above suggested to use this shift operator:

    outcome=rand()&#37;2; //this is bad
    .....
    outcome=(rand()&0x4000)>>14; //this is better

    and i said it wasnt working as it supposed to. Thats why i stuck with the modulus.
    Thanks for the explanation!
    Using Windows 10 with Code Blocks and MingW.

  8. #23
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Ducky View Post
    Maxorator your oparation gives always the same.
    With the modulus it changes at least, even if its a bit predictable, not much though.
    Try it if you dont believe me. I simplified the code.

    Code:
    #include <ctime>
    #include <iostream>
    #include <cstdlib>
    #include <windows.h>
    using namespace std;
    
    int x;                               // Move this down into main, don't make it a global
    
    int main()
    {
                                         // Put srand up here for crying out loud!!!
    	for(;;)
    	{
        	    int headCount=0;
    	    int tailCount=0;
                 for (int i=1; i<=6; i++)
        	    {
                   Sleep(839);           // This is a pointless waste of time - remove this line!!!
                   srand(time(NULL));    // no No NO! Not here!!!
    	        x =  rand() %2;
             
        		if (x == 0)
        		{
        			cout << " T, ";
        			tailCount++;
                    }
                    else
                   { 
        			cout << " H, ";
        			headCount++;
                   }
            }
        	cout << "\nHead " << headCount << endl;
        	cout << "Tail "   << tailCount << endl;
            system ("pause");
        }
        return 0;
    }
    AAAAARGH - It's like talking to a brick wall!...

    DO NOT CALL srand MORE THAN ONCE IN YOUR PROGRAM
    Read the FAQ already!

    Also, learn to indent code properly and replace tabs with the correct number of spaces before posting, and read the other comments inside the above code.
    Last edited by iMalc; 06-07-2008 at 03:03 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #24
    Registered User
    Join Date
    May 2008
    Posts
    81
    Quote Originally Posted by iMalc View Post
    AAAAARGH - It's like talking to a brick wall!...

    DO NOT CALL srand MORE THAN ONCE IN YOUR PROGRAM
    Read the FAQ already!

    Also, learn to indent code properly and replace tabs with the correct number of spaces before posting, and read the other comments inside the above code.
    does anyone know specifically why srand() shouldn't be called more than once, apart from that fact that it is redundant? As I understand it, the purpose of calling srand() is simply to seed the prng. as such, one would get more random output if srand() is seeded (differently) multiple times.

    for my program, i seed srand() with the output of the mersenne prng once for each iteration of a for loop, which loops around 10,000 times...and that gives me highlly random data.

  10. #25
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> one would get more random output if srand() is seeded (differently) multiple times.

    What do you mean by more random? What are you measuring that makes you think that your data is more random than it would be if you just used srand() once (or if you just used the mersenne twister prng without rand)?

    As I said earlier, seeding srand every time through the loop should give you identical results as just using the mersenne twister without rand(). That's because if you seed srand and call rand one time you are not getting a random number, you are getting a number that directly corresponds to the value you pass to srand.

  11. #26
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Technically, srand just gives the random number generator a number to work with.
    When calling rand, it will apply an algorithm on that number, I would believe, to give you a different number each time you call it.
    However, if you call srand again, you will reset that algorithm. Plus the fact that you seed it with the time, you would get very similar results all the time.
    Consider that.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #27
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by shawnt View Post
    does anyone know specifically why srand() shouldn't be called more than once, apart from that fact that it is redundant? As I understand it, the purpose of calling srand() is simply to seed the prng. as such, one would get more random output if srand() is seeded (differently) multiple times.

    for my program, i seed srand() with the output of the mersenne prng once for each iteration of a for loop, which loops around 10,000 times...and that gives me highlly random data.
    Obviously my response wasn't big enough, bold enough or capitalised enough...
    Basically if you don't understand something then you've got to take the advice of those that do understand it...

    If anything, by seeding it more often you make the results LESS random due to the fact that you shorten the period of the PRNG.
    If you properly seed it ONLY ONCE then you will get a properly random sequence of length 2^32 or 2^64 etc before it repeats, depending on how your compiler implements it.
    If you re-seed it then what that does is forgets where it was in that sequence and jumps to another point in the sequence, including potentially the point just before where you were, meaning that you could cause the last few results to be repeated identically again almost immediately which is BAD.

    Btw, there is no such thing as using rand to make something that is more random! The only thing you can improve about it is to even out the distribution over the typical code that simply uses mod with n to give 0 .. n-1. For most practical purposes you will never notice a teensy bit of bias though anyway, that is if the number you mod with happens to even produce any bias to begin with!

    If you have a superrior PRNG such as mersenne then for goodness sakes just use that. If you need cryptographically secure random numbers then you use the Crypto API.
    Last edited by iMalc; 06-07-2008 at 10:39 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  13. #28
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    Thanks iMalc for clearing this up.

    Its true that its not easy to understand what srand() is doing exactly.
    I thought that it was giving a random number like 2333 to rand() to start with thats why i changed it everytime.

    As for the indentation, it gets messed up when you copy/paste it and its pretty hard to fix it.
    You need to edit it several times.
    Using Windows 10 with Code Blocks and MingW.

  14. #29
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Ducky View Post
    I thought that it was giving a random number like 2333 to rand() to start with thats why i changed it everytime.
    It is giving rand a number to play with, but rand randomizes that number each time it's called.

    As for the indentation, it gets messed up when you copy/paste it and its pretty hard to fix it.
    You need to edit it several times.
    As iMalc has already mentioned, if you stop mixing spaces and tabs in your code, it won't be messed up when you copy and paste it. Choose one.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #30
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Quote Originally Posted by Elysia View Post
    I find that the higher bits change more seldom than the lower bits, since the high bit that was shifted out stayed the same throughout all the numbers, so I'm afraid it isn't as viable an option, either.
    This (http://c-faq.com/lib/notveryrand.html) seems to say differently.

    "For this reason, it's preferable to use the higher-order bits"
    "The Internet treats censorship as damage and routes around it." - John Gilmore

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. random to int?
    By psyadam in forum C# Programming
    Replies: 7
    Last Post: 07-22-2008, 08:09 PM
  2. Lesson #3 - Math
    By oval in forum C# Programming
    Replies: 2
    Last Post: 04-27-2006, 08:16 AM
  3. Another brain block... Random Numbers
    By DanFraser in forum C# Programming
    Replies: 2
    Last Post: 01-23-2005, 05:51 PM
  4. How do I restart a random number sequence.
    By jeffski in forum C Programming
    Replies: 6
    Last Post: 05-29-2003, 02:40 PM
  5. Best way to generate a random double?
    By The V. in forum C Programming
    Replies: 3
    Last Post: 10-16-2001, 04:11 PM