RNG problems

I have two problems, I am using c++ in visual studio for windows. I am making a random number generator as a class to be used with various projects of mine. Only using it in one program so far though.

First problem, 75% of all the generated numbers are in the lowest 20% of the range. ( I am trying to get a range evenly from -a to a, by "random number %(a*2)-a" )

the built in generator in <random> was giving me this problem so I found a better generator, the one below,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
The following xorshift+ generator, is a variation with 128 bits of state, a maximal period of 2128 − 1[8] and passes BigCrush:
This generator is one of the fastest generator passing BigCrush;[4] however, it is only 1-dimensionally equidistributed.

#include <stdint.h>
 
/* The state must be seeded so that it is not everywhere zero. */
uint64_t s[2];
 
uint64_t xorshift128plus(void) {
	uint64_t x = s[0];
	uint64_t const y = s[1];
	s[0] = y;
	x ^= x << 23; // a
	x ^= x >> 17; // b
	x ^= y ^ (y >> 26); // c
	s[1] = x;
	return x + y;
}


I still have the exact same problem, so I figure it must be how I am using it.

(Also, a side question, I haven't been able to find out what x ^= y does. I did figure out that using << or >> does something with shifting bits but I don't really understand that. If someone could explain what this generator is doing and how would be appreciated.)

So back to the primary issue,

the code I'm using,

location is a type that holds three doubles with some comparison functions. represents 3d coordinates.

lrand is my random function that takes a range and return a value between 0 and range parameter as a double

newLoca is a function that checks the input location against a list of current locations to ensure none are within a distance of the second parameter and returns a bool value of whether the new location was too close to an existing location.

mL is the range limit (stands for map limit)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
lrand(int range){
	double X = (rn.rnd());//returns a random number from the above code
	unsigned long long Y = X;// makes it an integral type
	X = Y % range;//limits to range
	return X;
}//close lrand


do{
		location trip2(
lrand(mL * 2) - mL, //each parameter
lrand(mL * 2) - mL, 
lrand(mL * 2) - mL);// make a new location

		if (!newLoca(trip2, 10)){ //checks to prevent clipping objects,
err.rep("mapstream", "eShell", 228, "newLocation was bad");//error callout if new location would clip another, not needed but fun for the moment
		continue;//restart in the case of a bad location
		}//close if
	} while (iter>0);



So I primarily need this to have objects evenly spaced across the available environment and not in the bottom fifth.

return results from this generator,
range limit, -150000 to 150000
highest result, 149904
lowest result, -149680
breakdown of result range by fifths for one run through
0% - 20%: 350 results
20% - 40%: 62 results
40% - 60%: 66 results
60% - 80%: 53 results
80% - 100%: 57 results


edit: not sure why I get these results, but when I examine the locations in a 3d environment they actually appear evenly distributed.
Last edited on
I have two problems, I am using c++ in visual studio for windows.

First problem, 75% of all the generated numbers are in the lowest 20% of the range. ( I am trying to get a range evenly from -a to a, by "random number %(a*2)-a" )

the built in generator in <random> was giving me this problem so I found a better generator, the one below,


What distribution were you using?

When using a uniform_real_distribution my results don't jive with yours at all.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <random>
#include <vector>

int main()
{

    double lower_limit = -15000;
    double upper_limit = 15000;
    double range = upper_limit - lower_limit ;

    std::mt19937 rng((std::random_device())());
    std::uniform_real_distribution<double> dist(lower_limit, upper_limit);

    double highest_result = lower_limit -1;
    double lowest_result = upper_limit + 1;

    const unsigned samples = 1000000;
    std::vector<unsigned> block_count(5);

    for (unsigned i = 0; i < samples; ++i)
    {
        double value = dist(rng);

        if (value < lowest_result)
            lowest_result = value;

        if (value > highest_result)
            highest_result = value;

        for (unsigned i = 0; i < 5; ++i)
        {
            if (value - lower_limit < (range / 5.0) * (i + 1))
            {
                ++block_count[i];
                break;
            }
        }
    }

    std::cout << "range limit, " << lower_limit << " to " << upper_limit << '\n';
    std::cout << "highest result, " << highest_result << '\n';
    std::cout << "lowest result, " << lowest_result << '\n';
    std::cout << "breakdown of result range by fifths for one run through\n";

    for (unsigned i = 0; i < 5; ++i)
        std::cout << "to " << ((i + 1) / 5.0)*100.0 << "%: " << block_count[i] << " results\n";
}


range limit, -15000 to 15000
highest result, 15000
lowest result, -15000
breakdown of result range by fifths for one run through
to 20%: 199980 results
to 40%: 199864 results
to 60%: 200011 results
to 80%: 200212 results
to 100%: 199933 results


http://ideone.com/Shkwx7
"What distribution were you using?"

I have no idea what this is.

originally I used srand() to seed, then got values from rand(). Didn't call any other functions related to random numbers.

Same case with the new generator, I give it a seed, and then take results from the formula.

I think my testing results may have been skewed somehow, though I'm not sure how it could be. When I view the points in 3d they appear evenly distributed.

I basically run each location (after generating them) through min/max checking, then through this,

if (itemLocaX[iter].outX() < (mL / 5)){zoneX1++;}
else if (itemLocaX[iter].outX() < ((mL / 5) * 2)){ zoneX2++; }
else if (itemLocaX[iter].outX() < ((mL / 5) * 3)){ zoneX3++; }
else if (itemLocaX[iter].outX() < ((mL / 5) * 4)){ zoneX4++; }
else if (itemLocaX[iter].outX() < mL){ zoneX5++; }

repeated for y and z, then collated together.

So I'm not sure how it can be skewed.

Interestingly, the original generator did indeed have the locations all towards the bottom of the map.


In any case, I still don't know what the new generator is doing, nor do I have any clue why my checker is giving me the results it is.
Last edited on
I have no idea what this is.

This page defines what a distribution is
http://www.cplusplus.com/reference/random/
Thanks for that. I would say then that I haven't been using one.

Now I just need to figure out why my test has been skewed. I got the rest of my code working, so now I need other layout options and that means tests to tell me when they're working.
Topic archived. No new replies allowed.