patterncppMinor
What do you think about this uint64 random generator?
Viewed 0 times
thisrandomyouwhatuint64generatoraboutthink
Problem
I've looked for a good method to generate an integer inside a range of values. I think using modulo is not a good method because the values are not perfectly mapped in the range. So I mapped the pseudo random generated number in the range by using double variables types.
What do you think about this method? I know that performance is not better when using a modulo. How would you improve the method or the performance by keeping a perfect match?
NEW VERSION:
```
// count setted bits at the right of a mask
quint8 bitCountRightMask(quint64 mask)
{
quint8 bc = 0;
while (mask & 1)
{
mask >>= 1;
bc++;
}
return bc;
}
const quint64 uint64_max = 0xffffffffffffffff;
const int bitCountRandMax = bitCountRightMask(RAND_MAX);
// randomise an uint64 variable
quint64 rand64()
{
quint64 myRand = qrand();
if (uint64_max > RAND_MAX)
{
int i = qCeil(64 / (double)bitCountRandMax) - 1;
do
{
myRand high)
{
qSwap(low, high);
}
return low + (rand64() % (high - low + 1));
}
// randomize an uint64 variable between low and high (precise method (double))
quint64 prand64(quint64 low, quint64 high)
{
if (low == 0 && high == 0)
{
return rand64();
}
else if (low > high)
{
qSwap(low, high);
}
quint64 myRand = rand64();
if (myRand == uint64_max)
{
return high
What do you think about this method? I know that performance is not better when using a modulo. How would you improve the method or the performance by keeping a perfect match?
quint32 randquint32(quint32 low, quint32 high)
{
const quint32 uint_max = 0xffffffff;
if (low == 0 && high == 0)
{
high = uint_max;
if (RAND_MAX > high)
{
return (qrand() & high);
}
}
else if (low > high)
{
qSwap(low, high);
}
const quint8 numberOfBits = bitCount(RAND_MAX);
quint32 myRand = 0;
int i = qCeil(((double)32) / ((double)numberOfBits));
while (i--)
{
myRand += qrand();
if (i)
{
myRand >= 1;
}
return count;
}NEW VERSION:
```
// count setted bits at the right of a mask
quint8 bitCountRightMask(quint64 mask)
{
quint8 bc = 0;
while (mask & 1)
{
mask >>= 1;
bc++;
}
return bc;
}
const quint64 uint64_max = 0xffffffffffffffff;
const int bitCountRandMax = bitCountRightMask(RAND_MAX);
// randomise an uint64 variable
quint64 rand64()
{
quint64 myRand = qrand();
if (uint64_max > RAND_MAX)
{
int i = qCeil(64 / (double)bitCountRandMax) - 1;
do
{
myRand high)
{
qSwap(low, high);
}
return low + (rand64() % (high - low + 1));
}
// randomize an uint64 variable between low and high (precise method (double))
quint64 prand64(quint64 low, quint64 high)
{
if (low == 0 && high == 0)
{
return rand64();
}
else if (low > high)
{
qSwap(low, high);
}
quint64 myRand = rand64();
if (myRand == uint64_max)
{
return high
Solution
DONT DO THIS
It seems like you are trying to increase the range of random numbers.
What you are doing is screwing up the distribution of the random numbers and thus making them less random. Have you tried plotting a histogram to show the distribution.
Luckily for you your system probably only has 32 bit rands and thus this is not changing anything; as the loop is only done once.
ASSUMPTION HERE
Is this not the whole point of all the work to avoid this:
There is plenty of documentation on the web of how to do this correctly please try and find rather than re-invent something like this. Random number generation is a non trivial task and exceedingly hard to get correct. Don't mess with it unless you have a PhD in probability.
Rand done properly: https://stackoverflow.com/a/10219422/14065
while (i--)
{
myRand += rand();
if (i)
{
myRand <<= numberOfBits;
}
}It seems like you are trying to increase the range of random numbers.
What you are doing is screwing up the distribution of the random numbers and thus making them less random. Have you tried plotting a histogram to show the distribution.
Luckily for you your system probably only has 32 bit rands and thus this is not changing anything; as the loop is only done once.
ASSUMPTION HERE
static const unsigned long uint_max = 0xffffffff; // assuming that long is 32 bits
// long has at least 32 bits but can be larger.Is this not the whole point of all the work to avoid this:
if (high < RAND_MAX)
{
return (rand() & high); // basically this is the same as using
} // % high. You are folding at high
// unless RAND_MAX is a multiple of high
// then you have an uneven distribution.There is plenty of documentation on the web of how to do this correctly please try and find rather than re-invent something like this. Random number generation is a non trivial task and exceedingly hard to get correct. Don't mess with it unless you have a PhD in probability.
Rand done properly: https://stackoverflow.com/a/10219422/14065
Code Snippets
while (i--)
{
myRand += rand();
if (i)
{
myRand <<= numberOfBits;
}
}static const unsigned long uint_max = 0xffffffff; // assuming that long is 32 bits
// long has at least 32 bits but can be larger.if (high < RAND_MAX)
{
return (rand() & high); // basically this is the same as using
} // % high. You are folding at high
// unless RAND_MAX is a multiple of high
// then you have an uneven distribution.Context
StackExchange Code Review Q#30250, answer score: 6
Revisions (0)
No revisions yet.