1

I have written a random number generator using srand(), which creates an array of random numbers of given size. I would like my random numbers taking values up to 1000.000 and to get this, I've defined each entry of the array as rand()%1000000 in the code below. The weird thing is that, the random values are all up to around 30.000 and the bigger random numbers such as 987.623 are not created i.e. the digit count of the random numbers are not more than 5. Does anyone have any idea of why is this happening? Is there another way (function) that you can offer to get random numbers bigger than these ones?

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <time.h>
#include <cmath>
#include <vector>
using namespace std;

int * rng(int size) {
    int* a = NULL;
    a = new int[size];
    for (int i = 0; i < size; i++) {
        a[i] = rand() % 1000000;
        if (a[i] == 0) {
            a[i] += 1;
        }
    }
    for (int j = 0; j < size; j++) {
        cout << a[j] << " ";
    }
    delete[] a;
    a = NULL;
    return a;
}

int main() {   
    srand(time(NULL)); 
    int size;
    int* x;
    ifstream myfile("size.txt");
    ofstream outfile("input.txt");
    while (myfile>>size) {   
        x=rng(size);
        if (outfile.is_open()) {    
            for(int count = 0; count < size; count ++) {
                outfile<< x[count] << " " ;
            } 
        myfile.close();
        }       
    }
    return 0;
    delete [] x;  
    x = NULL;
}
Chris Maes
  • 35,025
  • 12
  • 111
  • 136
esra
  • 201
  • 2
  • 8
  • As a side note, your code produces memory leaks because everything that comes after the `return a;` will not be executed. Use a debugger to step through the code. –  Feb 07 '17 at 17:53
  • Thanks Raw N 5, i'll fix it. – esra Feb 07 '17 at 17:54
  • 2
    Possible duplicate of [Extend rand() max range](http://stackoverflow.com/questions/9775313/extend-rand-max-range) – Alex K. Feb 07 '17 at 17:54
  • 1
    Also note your not actually calling srand() – Alex K. Feb 07 '17 at 17:55
  • Further, consider using the better functions and classes from – The Techel Feb 07 '17 at 17:56
  • Why all the downvotes? This question is well written, and there is good mention of the observed behaviour. – Bathsheba Feb 07 '17 at 18:02
  • @Bathsheba I completely agree with you. –  Feb 07 '17 at 18:04
  • 2
    `rng()` will now always return null, you don't need to delete `a` in the function. Consider @Bathsheba s alternative to return a `std::vector` instead or just delete after use. Also people love to spam the dv button when there's unformatted code in sight, just try and make sure it copy s correctly :) – George Feb 07 '17 at 18:11
  • @AlexK. Actually I have used srand() in main function but I have not added it here the first place. Now it can bee seen there. – esra Feb 07 '17 at 18:15
  • @RawN I have fixed the memory leak thanks. – esra Feb 07 '17 at 18:21

2 Answers2

6

RAND_MAX on your machine is obviously close to or at the minimum permitted by the standard: 32767.

There are plenty of alternatives available which offer better periodicity. Mersenne Twister is one such good alternative and forms part of the C++11 standard.

Also note that the statements after your return statement are unreachable. Consider a

std::vector<int>

as the return type.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
3

According to the documentation, the rand() function returns a number between 0 and RAND_MAX, which, again according to the documentation, is implementation-defined. "Implementation defined" means "whatever your compiler vendor wants it to be". In this case, your compiler vendor decided that it should be about 30000, in all likelihood 32767, in all likelihood in order to avoid breaking compatibility with some old, 16-bit version of their compiler.

You could choose another compiler, or you could do some trick, like the following:

int my_random_number = rand() ^ (rand() << 15);

The above assumes that your rand() function has a 15-bit range (that's numbers from 0 to 32767) so it concatenates 15 bits from one invocation with another 15 bits from another invocation, yielding a total of 30 bits, which has a range far greater than the 0 to 1.000.000 that you need. This concatenation is achieved by shifting the result of the second invocation to the left by 15 bits, and then XORing together the two results.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • Thanks. I'm using Dev C++, will try some others – esra Feb 07 '17 at 18:16
  • "Implementation defined" means that the compiler writer can decide what the implementation does, **subject to constraints** in the standard. For `RAND_MAX`, the constraint is that its value must be at least 32767. "Implementation defined" also means that the implementation **must document** its behavior. – Pete Becker Feb 07 '17 at 18:16
  • I updated my answer with an explanation. Note that this is just a quick and dirty hack. In the good days, things like this would pass as cool. Nowadays they tend to be frowned upon. But sometimes they are useful in helping us to keep going without getting stuck on a detail. – Mike Nakis Feb 07 '17 at 18:29
  • 1
    Mike Thanks a lot:) – esra Feb 07 '17 at 18:31
  • I think the XOR trick compromises the statistical properties of the generator. I think it fails chi square tests for uniformity, particularly if the multiplication factor in the linear congruential generator is small. Use it very carefully. – Bathsheba Feb 07 '17 at 18:43
  • @Bathsheba my reasoning for using XOR is as follows: if `rand()` returns max 15 bits, there will be no overlap, so it should work fine, because each set of 15 bits will be XORed with zeros, so the result would be the same as ORing the two values together. But if `rand()` by any chance happens to return more than 15 bits, then OR will probably produce worse results than XOR, because with OR the overlapping bits will have twice the chances of being turned into 1s, while with XOR a 1 overlapping a 1 will yield a 0. – Mike Nakis Feb 07 '17 at 18:46
  • Yes it sounds ingenious but it reminds me of an IBM rand implementation that swapped the first and last bits - and that completely ruined that generator. – Bathsheba Feb 07 '17 at 18:48
  • @Bathsheba Yes, it is true that when juggling bits around one needs to be very careful, because our theories of how things will work sometimes bear no relation to how things actually end up working. It happens even to very smart people. – Mike Nakis Feb 07 '17 at 18:54