C++ generating random numbers

后端 未结 11 1566
我寻月下人不归
我寻月下人不归 2020-12-01 10:49

My output is 20 random 1\'s, not between 10 and 1, can anyone explain why this is happening?

#include  
#include  
#include <         


        
相关标签:
11条回答
  • 2020-12-01 11:13

    It is one of the simplest logics, got it from a blog. in this logic you can limit the random numbers with that given modulus(%) operator inside the for loop, its just a copy and paste from that blog, but any way check it out:

    // random numbers generation in C++ using builtin functions
    #include <iostream>
    
    using namespace std;
    
    #include <iomanip>
    
    using std::setw;
    
    #include <cstdlib>   // contains function prototype for rand
    
    int main()
    {
    // loop 20 times
    for ( int counter = 1; counter <= 20; counter++ ) {
    
        // pick random number from 1 to 6 and output it
        cout << setw( 10 ) << ( 1 + rand() % 6 );
    
        // if counter divisible by 5, begin new line of output
        if ( counter % 5 == 0 )
            cout << endl;
    
    }
    
    return 0;  // indicates successful termination
    
    } // end main
    

    - See more at: http://www.programmingtunes.com/generation-of-random-numbers-c/#sthash.BTZoT5ot.dpuf

    0 讨论(0)
  • 2020-12-01 11:15

    What about using a condition to check if the last number is the same as the current one? If the condition is met then generate another random number. This solution works but it will take more time though.

    0 讨论(0)
  • 2020-12-01 11:17

    A somewhat late answer, but it should provide some additional information if the quality of the generation is important. (Not all applications need this—a slight bias is often not a problem.)

    First, of course, the problem in the original code is the fact that range * rand() has precedence over the following division, and is done using integer arithmetic. Depending on RAND_MAX, this can easily result in overflow, with implementation defined results; on all implementations that I know, if it does result in overflow (because RAND_MAX > INT_MAX / range, the actual results will almost certainly be smaller than RAND_MAX + 1.0, and the division will result in a value less than 1.0. There are several ways of avoiding this: the simplest and most reliable is simply rand() % range + lowest.

    Note that this supposes that rand() is of reasonable quality. Many earlier implementations weren't, and I've seen at least one where rand() % 6 + 1 to simulate a dice throw alternated odd and even. The only correct solution here is to get a better implementation of rand(); it has lead to people trying alternative solutions, such as (range * (rand() / (RAND_MAX + 1.0))) + lowest. This masks the problem, but it won't change a bad generator into a good one.

    A second issue, if the quality of the generation is important, is that when generating random integers, you're discretizing: if you're simulating the throw of a die, for example, you have six possible values, which you want to occur with equal probability. The random generator will generate RAND_MAX + 1 different values, with equal probability. If RAND_MAX + 1 is not a multiple of 6, there's no possible way of distributing the values equaly amont the 6 desired values. Imagine the simple case where RAND_MAX + 1 is 10. Using the % method above, the values 1–4 are twice as likely as the the values 5 and 6. If you use the more complicated formula 1 + int(6 * (rand() / (RAND_MAX + 1.0))) (in the case where RAND_MAX + 1 == 10, it turns out that 3 and 6 are only half as likely as the other values. Mathematically, there's simply no way of distributing 10 different values into 6 slots with an equal number of elements in each slot.

    Of course, RAND_MAX will always be considerably larger than 10, and the bias introduced will be considerably less; if the range is significantly less than RAND_MAX, it could be acceptable. If it's not, however, the usual procedure is something like:

    int limit = (RAND_MAX + 1LL) - (RAND_MAX + 1LL) % range;
                //  1LL will prevent overflow on most machines.
    int result = rand();
    while ( result >= limit ) {
        result = rand();
    }
    return result % range + lowest;
    

    (There are several ways of determining the values to throw out. This happens to be the one I use, but I remember Andy Koenig using something completely different—but which resulted in the same values being thrown out in the end.)

    Note that most of the time, you won't enter the loop; the worst case is when range is (RAND_MAX + 1) / 2 + 1, in which case, you'll still average just under one time through the loop.

    Note that these comments only apply when you need a fixed number of discrete results. For the (other) common case of generating a random floating point number in the range of [0,1), rand() / (RAND_MAX + 1.0) is about as good as you're going to get.

    0 讨论(0)
  • 2020-12-01 11:20

    I suggest you replace rand()/(RAND_MAX + 1.0) with range*double(rand())/(RAND_MAX + 1.0)). Since my solution seems to give headaches ...

    possible combinations of arguments:

    • range*rand() is an integer and overflows.
    • double(range*rand()) overflows before you convert it to double.
    • range*double(rand()) is not overflowing and yields expected results.

    My original post had two braces but they did not change anything (results are the same).

    0 讨论(0)
  • 2020-12-01 11:21

    Because, on your platform, RAND_MAX == INT_MAX.

    The expression range*rand() can never take on a value greater than INT_MAX. If the mathematical expression is greater than INT_MAX, then integer overflow reduces it to a number between INT_MIN and INT_MAX. Dividing that by RAND_MAX will always yield zero.

    Try this expression:

    random_integer = lowest+int(range*(rand()/(RAND_MAX + 1.0)))
    
    0 讨论(0)
  • 2020-12-01 11:21

    Visual studio 2008 has no trouble with that program at all and happily generates a swathe of random numbers.

    What I would be careful of is the /(RAND_MAX +1.0) as this will likely fall foul of integer problems and end up with a big fat zero.

    Cast to double before dividing and then cast back to int afterwards

    0 讨论(0)
提交回复
热议问题