5

Im currently having trouble generating random numbers between -32.768 and 32.768. It keeps giving me the same values but with a small change in the decimal field. ex : 27.xxx.

Heres my code, any help would be appreciated.

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

int main()
{
    srand( time(NULL) );
    double r = (68.556*rand()/RAND_MAX - 32.768);
    cout << r << endl;
    return 0;
}
bames53
  • 86,085
  • 15
  • 179
  • 244
Olivier
  • 1,981
  • 7
  • 24
  • 29
  • Have you tried using a loop. Since time(NULL) doesn't change that much from one second to the next, chances are that you get the same number each time. gettimeofday()'s microsecond count may also work better. – Mats Petersson Feb 01 '13 at 02:27
  • @MatsPetersson Passing consecutive values to `srand` should not and usually does not result in nearby results from even the first call to `rand`. (Though since there are no actual requirements on the quality of `rand`, I guess YMMV.) – aschepler Jun 25 '18 at 10:45

5 Answers5

12

I should mention if you're using a C++11 compiler, you can use something like this, which is actually easier to read and harder to mess up:

#include <random>
#include <iostream>
#include <ctime>


int main()
{
    //Type of random number distribution
    std::uniform_real_distribution<double> dist(-32.768, 32.768);  //(min, max)

    //Mersenne Twister: Good quality random number generator
    std::mt19937 rng; 
    //Initialize with non-deterministic seeds
    rng.seed(std::random_device{}()); 

    // generate 10 random numbers.
    for (int i=0; i<10; i++)
    {
      std::cout << dist(rng) << std::endl;
    }
    return 0;
}

As bames53 pointed out, the above code can be made even shorter if you make full use of c++11:

#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
#include <iterator>

int main()
{
    std::mt19937 rng; 
    std::uniform_real_distribution<double> dist(-32.768, 32.768);  //(min, max)
    rng.seed(std::random_device{}()); //non-deterministic seed
    std::generate_n( 
         std::ostream_iterator<double>(std::cout, "\n"),
         10, 
         [&]{ return dist(rng);} ); 
    return 0;
}
Carl
  • 43,122
  • 10
  • 80
  • 104
  • I needed the range i specified. I would have used (int) if i wanted that range – Olivier Feb 01 '13 at 03:02
  • 1
    Np, although you should also change the name of `normal_dist` since that should only be used with `std::normal_distribution` or similar. (normal distributions are also called Gaussian.) – bames53 Feb 01 '13 at 03:40
  • Lol. Can't believe I missed that. Updated again :) – Carl Feb 01 '13 at 03:41
  • note that uniform_real_distribution generates numbers in the range [min,max) ie will not generate max. – elegant dice Jun 06 '13 at 11:15
0

Also, If you are not using c++ 11 you can use the following function instead:

double randDouble(double precision, double lowerBound, double upperBound) {
 double random;
 random = static_cast<double>(((rand()%(static_cast<int>(std::pow(10,precision)*(upperBound - lowerBound) + 1))) + lowerBound*std::pow(10,precision)))/std::pow(10,precision);
 return random;
}
-1

I've added a for loop to your program:

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

int main () {
    srand(time (NULL));

    for (int i = 0; i < 10; ++i) {
        double r = ((68.556 * rand () / RAND_MAX) - 32.768);

        cout << r << endl;
    }

    return 0;
}

Example output:

 31.6779 
-28.2096
 31.5672
 18.9916 
-1.57149 
-0.993889
-32.4737
 24.6982
 25.936 
 26.4152

It seems Okay to me. I've added the code on Ideone for you.

Here are four runs:

 Run 1:
    -29.0863
    -22.3973
     34.1034
    -1.41155
    -2.60232
    -30.5257
     31.9254
    -17.0673
     31.7522
     28.227

Run 2:
    -14.2872
    -0.185124
    -27.3674
     8.12921
     22.4611
    -0.414546
    -21.4944
    -11.0871
     4.87673
     5.4545

Run 3:
    -23.9083
    -6.04738
    -6.54314
     30.1767
    -16.2224
    -19.4619
     3.37444
     9.28014
     25.9318
    -22.8807

Run 4:
     25.1364
     16.3011
     0.596151
     5.3953
    -25.2851
     10.7301
     18.4541
    -18.8511
    -0.828694
     22.8335

Perhaps you're not waiting at least a second between runs?

Ed The ''Pro''
  • 875
  • 10
  • 22
David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • I know that works, but when you run the program again, it keeps giving the same exact loop, but with small changes in the decimals. It gives the same exact loop – Olivier Feb 01 '13 at 02:31
  • Does my example output above look like the output on `ideone`? I ran it again and got, "30.3961 -13.9189 14.837 25.0323 -7.88294 24.9879 3.77392 18.4251 -8.11763 35.4337" then "25.0197 31.0387 -10.2659 -8.66796 -28.1792 -6.34876 7.51343 -32.6934 -23.4206 -16.8222". I'm not sure what you're doing wrong (unless you're waiting less than a second between runs), but the issue isn't in your code. – David Schwartz Feb 01 '13 at 02:42
  • Yea i copied your code from ideone. The only problem i have is that the first value in the loop is always the same (small change in decimal). The rest is random. – Olivier Feb 01 '13 at 02:52
  • Sounds like your PRNG is very low quality. Try adding an extra `rand()` call to the beginning of your program. (But, honestly, if you have any requirements all, don't use `rand()`. It has no quality guarantees.) – David Schwartz Feb 01 '13 at 02:54
  • yep ! it works for some reason. In my main program, i have to put a useless rand() floating to make everything work, kinda weird. Thanks alot ! – Olivier Feb 01 '13 at 02:56
-1

So, I think this is a typical case of "using time(NULL) isn't a great way of seeding random numbers for runs that start close together". There isn't that many bits that change in time(NULL) from one call to the next, so random numbers are fairly similar. This is not a new phenomena - if you google "my random numbers aren't very random", you'll find LOTS of this.

There are a few different solutions - getting a microsecond or nanosecond time would be the simplest choice - in Linux gettimeofday will give you a microsecond time as part of the struct.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
-1

It seams to be plainly obvious but some of the examples say otherwise... but i thought when you divide 1 int with another you always get an int? and you need to type cast each int to double/float before you divide them.

ie: double r = (68.556* (double)rand()/(double)RAND_MAX - 32.768);

also if you call srand() every time you call rand() you reset the seed which results in similar values returned every time instead of ''random'' ones.

Sellorio
  • 1,806
  • 1
  • 16
  • 32
  • The code doesn't do integer division; `68.556*rand()/RAND_MAX` is like: `(68.556*rand())/RAND_MAX`, which means the numerator is a `double`. – bames53 Feb 01 '13 at 03:30
  • ah, left to right, i see. I would still put it there to avoid unforeseen issues when i later change the code. – Sellorio Feb 01 '13 at 03:38