The design of Pseudo-random number generators is an archane art! The standard rand function usually carries a 'long' internally in order to produce a 'short' set of random values. By extension, a lrand function would need to carry a 'long long' internally to produce a 'long' set of random values. A 'long long' multiplication is much more complicated than simple 'long' multiplication so there are often performance issues associated with that kind of arithmatic, and 'long long' is a fairly recent invention, so lrand is not standard and thus not portable.
On the other hand sequential values from rand are fairly independent and the cycle length for rand is close to the cycle length of a 'long' counter. You can simply get two sequential rand values and merge them by multiplying the first by RAND_MAX and adding the second. (Or maybe that should be RAND_MAX + 1, or maybe you need to subtract one from the first value, or... You see what I mean by archane?)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2005-04-12
long random_number = (rand() << 15) | rand() ;
Will give you a 30bit random number (0 to 1,073,741,824). Other manipulations would proguce different numbers. But you have to be careful you do not create 'holes' or stuck bits, rand() only generated 15 bits, not 16.
Given the nature of pseudo-random number generation, there may be a flaw in this approach that makes it less than random in its distribution, but in most cases it will be adequate.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
While this is true for most implementations, there are implementations where RAND_MAX may be as small as 1023 (although the standard does call for a minimum value of 32767). If you're going to assume rand has a range of 0 to 32767 (that is the full 15 bit range), you should include:
if RAND_MAX != 32767
error Bad assumption -- RAND_MAX is not what I expect!
endif
someplace close to where you use this assumption.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2005-04-12
I am glad you pointed that out.
I knew that as I wrote it, but decided on simplicity. The OP already stated "RAND_MAX constant it is until 32768", so I formulated an answer for this specific case.
I should however have at least mentioned the portability issue.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Just thought I'd point out MersenneTwister is also available in GSL. Given the example above, replace gsl_rng_taus with gsl_rng_mt19937. There are also to older variants of MersenneTwister ( gsl_rng_mt19937_1998 and gsl_rng_mt19937_1999 ) and 30 or more other generators.
One caveat is that I had problems when placing all the lib/libgsl. files in Dev-Cpp/lib/ Perhaps I am not understanding something about doing that but for now I'm happy to static link and with only libgsl.a in place things seem to work ok.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2005-04-12
>From what I can tell you save one code step
Indeed, but first you have to obtain and install the library, and set up the project to use it. Many of the questions on the forum are from people having problems doing just that. Also the library may not be available on all platforms required (since the issue of portability was what sparked the response).
You also quoted my deliberatley 'overblown' solution, the first proposal:
long random_number = (rand() << 15) | rand() ;
Is much simpler. My second was an attempt at providing automatic portability, not necessary really, mtew's conditional compilation approach is probably adequate, the coder would then fix the implementation for the specific platform.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2005-04-12
>I think it is good that more than one option was presented to the OP
Agreed. I believe however that linking an entirely new and non-ISO standard library just to get a larger random number range is unnecessary. If however the application required GSL for other reasons, or perhaps required a better quality generator (i.e. closer to truly random), then its use might be justified.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
"Indeed, but first you have to obtain and install the library, and set up the project to use it."
with your class code, still need to get your code (or write similar) and most likely your going to want a project anyway. I'm suprised you even mention setting up the project. -lgsl isn't too tough.
"Also the library may not be available on all platforms required (since the issue of portability was what sparked the response)."
We know the OP is wanting to do something in Dev-Cpp. GSL will work on alot of platforms: http://www.gnu.org/software/gsl/#platforms
Maybe he was going to have portability problems just due to _lrand( ).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There is a GSL devpack available. I don't use it for random number as much as for special functions, like Bessel functions, that show up in diffraction patterns. Its a nice package I have used on IRIX, Cygwin and MinGW (maybe djgpp, its been a while though)
Wayne
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I just don't see the argument against GSL. I think few care about it being a shotgun at a snowball fight, it's proven code.
It seems to me that "long random_number = (rand() << 15) | rand() ;" performance in not 'long' but (LONG_MAX - 1) / 2 in 4.9.9.2 I'm sure I'll hear about it if it's just my imagination
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
hi,
in the first place, thanks to all.
Of all the options I prefer the clifford option, it is a portable and standard solution.
Whenever we can we should write standard code.
Tks you Clifford, I like your style.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2005-04-13
When I am doing hard maths, perhaps GSL is what I'll look at but this is easy. If distributing your code is likely, there are fewer hurdles if you avoid third-party libraries.
w.r.t. to "(LONG_MAX - 1) / 2". Yes, in my initial post I pointed out that it was only a 30bit generator (LONG_MAX/2 I think although it makes no difference LONG_MAX being an odd integer!). I posted a 32bit version as well, that required three calls to rand() just for the extra two bits. This may be unnecessary in most cases.
w.r.t. "I'm suprised you even mention setting up the project". - I always recommend using a project. Especially if you are employing non-standard libraries. Otherwise the compiler settings changes you apply for one program get applied to all programs you subsequently build, including any old code you might rebuild. Using a project, you start with a known good set of settings, and the settings can be kept with the source so that you always build the correct code.
Clifford
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
"Of all the options I prefer the clifford option, it is a portable and standard solution."
For PRNGs, that depends on what you're going to use it for.
With the standard rand(), the actual implementation is unknown - and may possibly be unsuitable for your purposes.
You might wish to reproduce your results on demand by using known seeds, but with unknown or different PRNG implementations your result would then not be portable.
The Mersenne Twister implementation I linked to is contained in a single header file, and supposedly is one of the fastest out there. It is relatively easy to distribute and link to since it is just a single file.
It isnt a port from C either - the interface is designed for C++.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anonymous
-
2005-04-13
> ...that depends on what you're going to use it for.
Indeed, and I think I made that point.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
A person used rand( ) implimented in a compiler and needed a larger output. Lets say rand's output was good enough for the task at hand, execpt for max value.
Is it valid to multiply a few rand( ) together? ( up to ULONG_LONG_MAX ) Without creating other problems?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
you needed to read what is it a random number first.....and later response ....i f you multiply the result by a long number, eskiusme, this number is not RANDOM !!!.
All numbers generated with rand() function must has a equal probability of generation, uniform distribution.
tks !!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
"you needed to read what is it a random number first.....and later response ....i f you multiply the result by a long number, eskiusme, this number is not RANDOM !!!."
Performing arithmetic operations (with a constant) on a number generated randomly or pseudo-randomly should not affect its randomness or pseudo-randomness, in my opinion.
You might get problems if you used the original sequence and mapped sequence together in a one-time pad, but that's another matter.
I'm not sure if multiplying 2 n-bit random numbers gives a random number of 2n-bits, or merely a 2n-bit long number with n+1 bits of randomness (if that could be so easily measured).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Multiplying random numbers together does not give random numbers. Try writing a table of all possibilities that are possible if you did this with two 6-sided dice. In this the number 6 would have 4 ways of being made (1x6 2x3 3x2 6x1) whereas 36 would only have 1 (6x6). Also this method would never give a prime number futher making it useless.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Well I can see one direction the question could lead: Is the bit shifting method just a perverse method of mutiplication? Sorry I don't have an answer to that but someone here likely does...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
bit shifting is equivalent to multiplying by a power of two, ie:
3 << 4 == 3 * (2 to the power of 4)
(This isn't entirely the case because if the number grows greater than the maximum number of bits in a long then you'll get some truly weird effects. But it will do for now)
A boolean OR is equivalent to an arithmetic Add if all of the bits in one of the numbers being ORed are zero for each corresponding one bit in the other number. Since we have shifted the first number further to the left than rand() can generate, this is guaranteed to be true.
So for Clifford's excellent long longrand = (rand() << 15) | rand();
gives f(a,b) = 32768 * a + b, where 0 < a < 32767 and 0 < b < 32767. Within these constraints, for any given a and b, there is a unique value for f(a,b).
Back to your original code, if you are trying to be strictly accurate, you will not be executing your if block with a probability of 1:100000 (0.00001).
Within the range of your new 30-bit rand function (from 0 to 1,073,741,823) there are 10,738 values that will satisfy your condition (% 100000 == 0)
This will give a random probability of 1: 100003. This may or may not be accurate enough for your application. If you're writing the code for an online casino which publishes its odds as 1 in 100000. then prepare to get sued......
If you use three rand()s and shift them into a long long, you'll be accurate enough, although your new 45-bit random number will be larger than the internal state of the rand() runction, so you'll have a problem there. One solution would to be to re-seed rand() in between the calls. There are problems with this though in that seeding in quick succession from, say, time(0) can result in a lack of randomness as well.
To get a genuine probabilty of 1:100000 you need to go to at least 40 bits, and preferably 45 bits to eliminate error. This means you might need to create your own random number generator!
Good luck,
Ian
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
hi,
I have got a problem. I working with rand function, but it not support long type.
On the cstdlib header file, the value of RAND_MAX constant it is until 32768. I need a bigger value, because I wrking with 10e5, 10e6 values.
Howevwe, in the Borland Compiler C++ 5.5.1 (CLI type), they have a header file (cstdlib), which support the long type, their function calls _lrand().
Please, somebody, may can me ????, tks !!!
p.s.: my source code:
if ((rand()% 100000) ==0)
return true;
else return false;
The design of Pseudo-random number generators is an archane art! The standard rand function usually carries a 'long' internally in order to produce a 'short' set of random values. By extension, a lrand function would need to carry a 'long long' internally to produce a 'long' set of random values. A 'long long' multiplication is much more complicated than simple 'long' multiplication so there are often performance issues associated with that kind of arithmatic, and 'long long' is a fairly recent invention, so lrand is not standard and thus not portable.
On the other hand sequential values from rand are fairly independent and the cycle length for rand is close to the cycle length of a 'long' counter. You can simply get two sequential rand values and merge them by multiplying the first by RAND_MAX and adding the second. (Or maybe that should be RAND_MAX + 1, or maybe you need to subtract one from the first value, or... You see what I mean by archane?)
You might try this:
http://gnuwin32.sourceforge.net/packages/gsl.htm
I made a little experiment:
include <iostream>
//#include <config.h> ??
include <gsl/gsl_rng.h>
using namespace std;
int main(int argc, char *argv[])
{
int target = 0;
unsigned long a = 0;
gsl_rng * r = gsl_rng_alloc (gsl_rng_taus);
gsl_rng_set ( r, time(NULL));
}
link library: -lgsl
Maybe it will meet your need?
long random_number = (rand() << 15) | rand() ;
Will give you a 30bit random number (0 to 1,073,741,824). Other manipulations would proguce different numbers. But you have to be careful you do not create 'holes' or stuck bits, rand() only generated 15 bits, not 16.
For example to get a full 32bit signed result:
long random_number = (rand() << 17) | (rand() << 2) | (rand() & 0x3) ;
Given the nature of pseudo-random number generation, there may be a flaw in this approach that makes it less than random in its distribution, but in most cases it will be adequate.
Clifford
While this is true for most implementations, there are implementations where RAND_MAX may be as small as 1023 (although the standard does call for a minimum value of 32767). If you're going to assume rand has a range of 0 to 32767 (that is the full 15 bit range), you should include:
if RAND_MAX != 32767
error Bad assumption -- RAND_MAX is not what I expect!
endif
someplace close to where you use this assumption.
I am glad you pointed that out.
I knew that as I wrote it, but decided on simplicity. The OP already stated "RAND_MAX constant it is until 32768", so I formulated an answer for this specific case.
I should however have at least mentioned the portability issue.
I suggest using the Mersenne Twister pseudo-random number generator:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
In particular, this C++ implementation might be useful:
http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html
Just thought I'd point out MersenneTwister is also available in GSL. Given the example above, replace gsl_rng_taus with gsl_rng_mt19937. There are also to older variants of MersenneTwister ( gsl_rng_mt19937_1998 and gsl_rng_mt19937_1999 ) and 30 or more other generators.
One caveat is that I had problems when placing all the lib/libgsl. files in Dev-Cpp/lib/ Perhaps I am not understanding something about doing that but for now I'm happy to static link and with only libgsl.a in place things seem to work ok.
>From what I can tell you save one code step
Indeed, but first you have to obtain and install the library, and set up the project to use it. Many of the questions on the forum are from people having problems doing just that. Also the library may not be available on all platforms required (since the issue of portability was what sparked the response).
You also quoted my deliberatley 'overblown' solution, the first proposal:
long random_number = (rand() << 15) | rand() ;
Is much simpler. My second was an attempt at providing automatic portability, not necessary really, mtew's conditional compilation approach is probably adequate, the coder would then fix the implementation for the specific platform.
Clifford
>I think it is good that more than one option was presented to the OP
Agreed. I believe however that linking an entirely new and non-ISO standard library just to get a larger random number range is unnecessary. If however the application required GSL for other reasons, or perhaps required a better quality generator (i.e. closer to truly random), then its use might be justified.
Clifford
"Indeed, but first you have to obtain and install the library, and set up the project to use it."
with your class code, still need to get your code (or write similar) and most likely your going to want a project anyway. I'm suprised you even mention setting up the project. -lgsl isn't too tough.
"Also the library may not be available on all platforms required (since the issue of portability was what sparked the response)."
We know the OP is wanting to do something in Dev-Cpp. GSL will work on alot of platforms:
http://www.gnu.org/software/gsl/#platforms
Maybe he was going to have portability problems just due to _lrand( ).
There is a GSL devpack available. I don't use it for random number as much as for special functions, like Bessel functions, that show up in diffraction patterns. Its a nice package I have used on IRIX, Cygwin and MinGW (maybe djgpp, its been a while though)
Wayne
I just don't see the argument against GSL. I think few care about it being a shotgun at a snowball fight, it's proven code.
It seems to me that "long random_number = (rand() << 15) | rand() ;" performance in not 'long' but (LONG_MAX - 1) / 2 in 4.9.9.2 I'm sure I'll hear about it if it's just my imagination
hi,
in the first place, thanks to all.
Of all the options I prefer the clifford option, it is a portable and standard solution.
Whenever we can we should write standard code.
Tks you Clifford, I like your style.
When I am doing hard maths, perhaps GSL is what I'll look at but this is easy. If distributing your code is likely, there are fewer hurdles if you avoid third-party libraries.
w.r.t. to "(LONG_MAX - 1) / 2". Yes, in my initial post I pointed out that it was only a 30bit generator (LONG_MAX/2 I think although it makes no difference LONG_MAX being an odd integer!). I posted a 32bit version as well, that required three calls to rand() just for the extra two bits. This may be unnecessary in most cases.
w.r.t. "I'm suprised you even mention setting up the project". - I always recommend using a project. Especially if you are employing non-standard libraries. Otherwise the compiler settings changes you apply for one program get applied to all programs you subsequently build, including any old code you might rebuild. Using a project, you start with a known good set of settings, and the settings can be kept with the source so that you always build the correct code.
Clifford
"Of all the options I prefer the clifford option, it is a portable and standard solution."
For PRNGs, that depends on what you're going to use it for.
With the standard rand(), the actual implementation is unknown - and may possibly be unsuitable for your purposes.
You might wish to reproduce your results on demand by using known seeds, but with unknown or different PRNG implementations your result would then not be portable.
The Mersenne Twister implementation I linked to is contained in a single header file, and supposedly is one of the fastest out there. It is relatively easy to distribute and link to since it is just a single file.
It isnt a port from C either - the interface is designed for C++.
> ...that depends on what you're going to use it for.
Indeed, and I think I made that point.
A person used rand( ) implimented in a compiler and needed a larger output. Lets say rand's output was good enough for the task at hand, execpt for max value.
Is it valid to multiply a few rand( ) together? ( up to ULONG_LONG_MAX ) Without creating other problems?
hi,
you needed to read what is it a random number first.....and later response ....i f you multiply the result by a long number, eskiusme, this number is not RANDOM !!!.
All numbers generated with rand() function must has a equal probability of generation, uniform distribution.
tks !!
"you needed to read what is it a random number first.....and later response ....i f you multiply the result by a long number, eskiusme, this number is not RANDOM !!!."
Performing arithmetic operations (with a constant) on a number generated randomly or pseudo-randomly should not affect its randomness or pseudo-randomness, in my opinion.
You might get problems if you used the original sequence and mapped sequence together in a one-time pad, but that's another matter.
I'm not sure if multiplying 2 n-bit random numbers gives a random number of 2n-bits, or merely a 2n-bit long number with n+1 bits of randomness (if that could be so easily measured).
Multiplying random numbers together does not give random numbers. Try writing a table of all possibilities that are possible if you did this with two 6-sided dice. In this the number 6 would have 4 ways of being made (1x6 2x3 3x2 6x1) whereas 36 would only have 1 (6x6). Also this method would never give a prime number futher making it useless.
"Multiplying random numbers together does not give random numbers."
It does (in a sense), though the distribution would not be very uniform.
"Also this method would never give a prime number futher making it useless."
It would, if one of the factors was 1, and the other was prime.
"Is it valid to multiply a few rand( ) together?"
Well I can see one direction the question could lead: Is the bit shifting method just a perverse method of mutiplication? Sorry I don't have an answer to that but someone here likely does...
bit shifting is equivalent to multiplying by a power of two, ie:
3 << 4 == 3 * (2 to the power of 4)
(This isn't entirely the case because if the number grows greater than the maximum number of bits in a long then you'll get some truly weird effects. But it will do for now)
A boolean OR is equivalent to an arithmetic Add if all of the bits in one of the numbers being ORed are zero for each corresponding one bit in the other number. Since we have shifted the first number further to the left than rand() can generate, this is guaranteed to be true.
So for Clifford's excellent long longrand = (rand() << 15) | rand();
gives f(a,b) = 32768 * a + b, where 0 < a < 32767 and 0 < b < 32767. Within these constraints, for any given a and b, there is a unique value for f(a,b).
Back to your original code, if you are trying to be strictly accurate, you will not be executing your if block with a probability of 1:100000 (0.00001).
Within the range of your new 30-bit rand function (from 0 to 1,073,741,823) there are 10,738 values that will satisfy your condition (% 100000 == 0)
This will give a random probability of 1: 100003. This may or may not be accurate enough for your application. If you're writing the code for an online casino which publishes its odds as 1 in 100000. then prepare to get sued......
If you use three rand()s and shift them into a long long, you'll be accurate enough, although your new 45-bit random number will be larger than the internal state of the rand() runction, so you'll have a problem there. One solution would to be to re-seed rand() in between the calls. There are problems with this though in that seeding in quick succession from, say, time(0) can result in a lack of randomness as well.
To get a genuine probabilty of 1:100000 you need to go to at least 40 bits, and preferably 45 bits to eliminate error. This means you might need to create your own random number generator!
Good luck,
Ian
rand() функсия асосан барои тавлиди ададҳои тасодуфии дар доираи int пешбинӣ шудааст, бинобар ин дастгирии long аз ҷониби он маҳдуд аст. Барои кор бо long ё unsigned long, беҳтар аст функсияҳои дигар мисли rand64() ё генераторҳои пешрафта истифода шаванд. Дар робита бо мавзӯи бозӣ, бояд гуфт, ки чунин механизмҳои тасодуфӣ дар казиноҳои онлайн, аз ҷумла дар 1win, барои таъмин кардани одилонагии натиҷаҳо истифода мешаванд. Ин казино дар Тоҷикистон фаъолият мекунад ва дорои василаи хуби бозӣ мебошад.
Last edit: ShuhratBoboyev 1 day ago