Thread: what went wrong with this code?

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    18

    what went wrong with this code?

    Hi. I wrote a code that rolls a dice 3000 times and counts number of sixes rolled then prints the amount. I noticed that no matter how many times I ran the code, I didn't get 500+ sixes. I thought it was strange, considering that there are 6 numbers and 3000 tosses. So in a "perfect" world there should be 500 counts of each numbers. I got curious and thought I should write a code that runs the main function until there are 500+ counts of sixes and prints out how many times the program ran until it reached 500 sixes. I know how to do it by writing if and else in the main function but Im currently learning about functions so I thought the best way to to it is by using functions only.

    this is what I did

    Code:
    //
    //  main.c
    //  oppgave 3-6 terning
    //
    //  Created by Aria Nemati on 07/04/2019.
    //  Copyright © 2019 Aria Nemati. All rights reserved.
    //
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    int terning(void);
    void print(int antall);
    
    
    int main(){
        
        int i;
        int x;
        int antall=0;
        int funksjon=1;
        
        printf("kaster en terning 3000 ganger!\n");
        
        srand(time(NULL));
    
    
        for (i=0; i<3000; i++){
        
                x = terning();
        
                if (x==6){
                    
                    antall++;
                   
                }
                }
       
        print(antall);
     
        /*while (antall < 440){
    
                main();
    
                funksjon++;
    
                }
    
        printf("antall ganger programmet er kjørt: %d" , funksjon);*/
        
        return 0;
        
        }
    
    
    
    
    int terning(void){
        
        int x = rand()%7;
        
        return x;
        
        }
    
    
    void print(int antall){
        
        printf("antall seksere: %d\n" , antall);
        
        }
    The parts i greyed out are the code I wrote that dont work. Please tell me where my thinking went wrong and how I should approach such tasks in the future. I want to improve the way I think when coding.

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    0 thru 6 is 7 numbers not 6.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  3. #3
    Registered User
    Join Date
    Apr 2019
    Posts
    18
    its supposed to be 1-6. I fixed that line by changinge to %6 +1.

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by mangekyou View Post
    its supposed to be 1-6. I fixed that line by changinge to %6 +1.
    The linear congruential pseudo-number generator is less random on its lower bits than the higher ones... Try this:

    Code:
    int x = ((rand() >> 29) % 6)+1;
    29 because you want just the upper 3 bits (RAND_MAX is 31 bits long). But if you want portability, must check how many bits RAND_MAX has.

    You can, also, do this:

    Code:
    int x = (((double)rand() / RAND_MAX) * 5 + 1;
    Last edited by flp1969; 04-07-2019 at 12:25 PM.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    If you need to care about the quality of your PRNG, then don't use rand(). If not, use rand() and don't bother trying to compensate for it typically being an LCG.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by flp1969 View Post
    The linear congruential pseudo-number generator is less random on its lower bits than the higher ones... Try this:

    Code:
    int x = ((rand() >> 29) % 6)+1;
    Since it's signed int, rand() returns only 31 bits of randomness (assuming int is 32 bits), so you need to shift by 28, not 29.

    But with 3 bits of randomness, you'll get 1 and 2 about twice as often as 3/4/5/6:

    Code:
    c@c:~$ cat 177334.c
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
            for (int i = 0; i < 1000000; ++i) {
                    printf("%d\n", ((rand() >> 28) % 6)+1);
            }
            return 0;
    }
    c@c:~$ ./177334 | sort | uniq -c | sort -n
     124476 6
     124905 3
     125251 4
     125358 5
     249919 2
     250091 1
    (Random values 0-5 map to 1-6, and random values 6-7 map to 1-2.)

  7. #7
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Quote Originally Posted by christop View Post
    Since it's signed int, rand() returns only 31 bits of randomness (assuming int is 32 bits), so you need to shift by 28, not 29.
    That depends on the implementation. The standard guaranties that RAND_MAX will be at least 32767, but that's about it. Modern PCs tend to use 31 bits, but I wouldn't rely on it. I've witnessed quite a bit of inconsistency across operating systems.
    Devoted my life to programming...

  8. #8
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by GReaper View Post
    That depends on the implementation. The standard guaranties that RAND_MAX will be at least 32767, but that's about it. Modern PCs tend to use 31 bits, but I wouldn't rely on it. I've witnessed quite a bit of inconsistency across operating systems.
    Of course, but I just wanted to show that using fewer bits from rand() can actually make the distribution of random numbers worse rather than better.

  9. #9
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by GReaper View Post
    That depends on the implementation. The standard guaranties that RAND_MAX will be at least 32767, but that's about it. Modern PCs tend to use 31 bits, but I wouldn't rely on it. I've witnessed quite a bit of inconsistency across operating systems.
    That's why I recommend to test the number of bits of RAND_MAX:

    Code:
    // GCC code.
    static int rand_bits;
    
    __attribute__((constructor))
    static void get_rand_bits( void )
    { rand_bits = 8*sizeof(int) - __builtin_clz( RAND_MAX ); }
    
    int rolldice( void ) { return ((unsigned)rand() >> (rand_bits - 3)) % 6 + 1; }
    Last edited by flp1969; 04-08-2019 at 03:42 PM.

  10. #10
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    flp1969: that main problem I tried to illustrate is that using the top 3 bits of rand() to roll a 6-sided die gives a very uneven distribution. Values 1 and 2 each have a 1:4 probability, while all other values each have only a 1:8 probability.

    That would give the user a 1:16 probability of getting snake eyes instead of the expected 1:36.

    (It should work fine with a d2, d4, d8, d16, etc die, since those are all powers of 2.)

    On the other hand, if you take only the top 3 bits, you could instead repeatedly generate a random number until it's in range:

    Code:
    int rolldice( void ) {
        int roll;
        do {
            roll = (unsigned)rand() >> (rand_bits - 3);
        } while (roll >= 6);
        return roll + 1;
    }
    (There are better ways to do this, but that shows the basic idea.)

    That'll give a much more uniform distribution.

  11. #11
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Quote Originally Posted by christop View Post
    flp1969: that main problem I tried to illustrate is that using the top 3 bits of rand() to roll a 6-sided die gives a very uneven distribution. Values 1 and 2 each have a 1:4 probability, while all other values each have only a 1:8 probability.
    I see your point and agree...

    My only point is to get a more "random" number from rand() we have to use the highest bits. Don't need to be only 3.
    I would avoid the loop. It is very unlikely, but it could iterate forever or take a long time...

    Personally I don't like LCG (for the randomness problem of lower bits) or Mersene Twister (too slow)... I've liked very much xorshift128+ or using RDRAND (on Intel platform, Haswell architecture or above, I believe).
    Last edited by flp1969; 04-08-2019 at 06:09 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What's wrong with this code?
    By andysalter in forum C Programming
    Replies: 2
    Last Post: 04-03-2013, 05:37 AM
  2. What is wrong with this code?
    By ElWhapo in forum Windows Programming
    Replies: 8
    Last Post: 01-25-2005, 12:51 PM
  3. anything wrong with this code?
    By thinhare in forum C Programming
    Replies: 24
    Last Post: 12-20-2004, 02:11 PM
  4. What is wrong with this code?
    By Tride in forum C++ Programming
    Replies: 7
    Last Post: 10-27-2003, 03:49 PM

Tags for this Thread