 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Jason Guest
|
Posted: Fri Feb 27, 2004 9:11 pm Post subject: random number code |
|
|
Hi,
I need a way to use random numbers in c++. In my c++ project, when using
the mingw compiler I used a mersenne twister that is publicly available and
this did its job well. Now I have shelled out on VC++ 6.0 compiling that
same code is proving difficult. I am not too worried how I generate random
numbers in c++, as long as it is sufficiently random.
Can anybody help me out in getting what I want from VC++?
If anybody wants the existing code along with errors generated by VC++ then
see below. Perhaps someone can explain what the problem is and how to fix
it. Sorry it is long.
On a separate point, as you might expect it is quite dismoralising to buy
something that promised to be able to compile ISO C++ and then to have
errors thrown at you from code that compiled fine before. I am not talking
about just this code, as I am faced with rewriting an entire project to fit
in with VC++. I'm thinking it is because I did not create the classes from
within VC++, so perhaps I can copy and paste code into the damn thing in
sections - any advice on this? I wanted VC++ to use mfc and make creating a
GUI simple, as well as to take advantage of its debugging facilities and
code hints. Will it really compile exactly the same as mingw compiler used
to in DevC++ or do I need to get a good VC++ book because it is different?
Any suggestions on what to read to get the best out of it?
code:
// mtrand.cpp, see include file mtrand.h for information
#include "mtrand.h"
// non-inline function definitions and static member definitions cannot
// reside in header file because of the risk of multiple declarations
// initialization of static private members
unsigned long MTRand_int32::state[n] = {0x0UL};
int MTRand_int32::p = 0;
bool MTRand_int32::init = false;
void MTRand_int32::gen_state() { // generate new state vector
for (int i = 0; i < (n - m); ++i)
state[i] = state[i + m] ^ twiddle(state[i], state[i + 1]);
for (int i = n - m; i < (n - 1); ++i)
state[i] = state[i + m - n] ^ twiddle(state[i], state[i + 1]);
state[n - 1] = state[m - 1] ^ twiddle(state[n - 1], state[0]);
p = 0; // reset position
}
void MTRand_int32::seed(unsigned long s) { // init by 32 bit seed
state[0] = s & 0xFFFFFFFFUL; // for > 32 bit machines
for (int i = 1; i < n; ++i) {
state[i] = 1812433253UL * (state[i - 1] ^ (state[i - 1] >> 30)) + i;
// see Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier
// in the previous versions, MSBs of the seed affect only MSBs of the array
state
// 2002/01/09 modified by Makoto Matsumoto
state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
}
p = n; // force gen_state() to be called for next random number
}
void MTRand_int32::seed(const unsigned long* array, int size) { // init by
array
seed(19650218UL);
int i = 1, j = 0;
for (int k = ((n > size) ? n : size); k; --k) {
state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) *
1664525UL))
+ array[j] + j; // non linear
state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
++j; j %= size;
if ((++i) == n) { state[0] = state[n - 1]; i = 1; }
}
for (int k = n - 1; k; --k) {
state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) *
1566083941UL)) - i;
state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines
if ((++i) == n) { state[0] = state[n - 1]; i = 1; }
}
state[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array
p = n; // force gen_state() to be called for next random number
}
//mtrand.h
#ifndef MTRAND_H
#define MTRAND_H
class MTRand_int32 { // Mersenne Twister random number generator
public:
// default constructor: uses default seed only if this is the first instance
MTRand_int32() { if (!init) seed(5489UL); init = true; }
// constructor with 32 bit int as seed
MTRand_int32(unsigned long s) { seed(s); init = true; }
// constructor with array of size 32 bit ints as seed
MTRand_int32(const unsigned long* array, int size) { seed(array, size);
init = true; }
// the two seed functions
void seed(unsigned long); // seed with 32 bit integer
void seed(const unsigned long*, int size); // seed with array
// overload operator() to make this a generator (functor)
unsigned long operator()() { return rand_int32(); }
~MTRand_int32() {} // destructor
protected: // used by derived classes, otherwise not accessible; use the
()-operator
unsigned long rand_int32(); // generate 32 bit random integer
private:
static const int n = 624, m = 397; // compile time constants
// the variables below are static (no duplicates can exist)
static unsigned long state[n]; // state vector array
static int p; // position in state array
static bool init; // true if init function is called
// private functions used to generate the pseudo random numbers
unsigned long twiddle(unsigned long, unsigned long); // used by
gen_state()
void gen_state(); // generate new state
// make copy constructor and assignment operator unavailable, they don't
make sense
MTRand_int32(const MTRand_int32&); // copy constructor not defined
void operator=(const MTRand_int32&); // assignment operator not defined
};
// inline for speed, must therefore reside in header file
inline unsigned long MTRand_int32::twiddle(unsigned long u, unsigned long v)
{
return (((u & 0x80000000UL) | (v & 0x7FFFFFFFUL)) >> 1)
^ ((v & 1UL) ? 0x9908B0DFUL : 0x0UL);
}
inline unsigned long MTRand_int32::rand_int32() { // generate 32 bit random
int
if (p == n) gen_state(); // new state vector needed
// gen_state() is split off to be non-inline, because it is only called once
// in every 624 calls and otherwise irand() would become too big to get
inlined
unsigned long x = state[p++];
x ^= (x >> 11);
x ^= (x << 7) & 0x9D2C5680UL;
x ^= (x << 15) & 0xEFC60000UL;
return x ^ (x >> 1 ;
}
// generates double floating point numbers in the half-open interval [0, 1)
class MTRand : public MTRand_int32 {
public:
MTRand() : MTRand_int32() {}
MTRand(unsigned long seed) : MTRand_int32(seed) {}
MTRand(const unsigned long* seed, int size) : MTRand_int32(seed, size) {}
~MTRand() {}
double operator()() {
return static_cast<double>(rand_int32()) * (1. / 4294967296.); } //
divided by 2^32
private:
MTRand(const MTRand&); // copy constructor not defined
void operator=(const MTRand&); // assignment operator not defined
};
// generates double floating point numbers in the closed interval [0, 1]
class MTRand_closed : public MTRand_int32 {
public:
MTRand_closed() : MTRand_int32() {}
MTRand_closed(unsigned long seed) : MTRand_int32(seed) {}
MTRand_closed(const unsigned long* seed, int size) : MTRand_int32(seed,
size) {}
~MTRand_closed() {}
double operator()() {
return static_cast<double>(rand_int32()) * (1. / 4294967295.); } //
divided by 2^32 - 1
private:
MTRand_closed(const MTRand_closed&); // copy constructor not defined
void operator=(const MTRand_closed&); // assignment operator not defined
};
// generates double floating point numbers in the open interval (0, 1)
class MTRand_open : public MTRand_int32 {
public:
MTRand_open() : MTRand_int32() {}
MTRand_open(unsigned long seed) : MTRand_int32(seed) {}
MTRand_open(const unsigned long* seed, int size) : MTRand_int32(seed,
size) {}
~MTRand_open() {}
double operator()() {
return (static_cast<double>(rand_int32()) + .5) * (1. / 4294967296.); }
// divided by 2^32
private:
MTRand_open(const MTRand_open&); // copy constructor not defined
void operator=(const MTRand_open&); // assignment operator not defined
};
// generates 53 bit resolution doubles in the half-open interval [0, 1)
class MTRand53 : public MTRand_int32 {
public:
MTRand53() : MTRand_int32() {}
MTRand53(unsigned long seed) : MTRand_int32(seed) {}
MTRand53(const unsigned long* seed, int size) : MTRand_int32(seed, size)
{}
~MTRand53() {}
double operator()() {
return (static_cast<double>(rand_int32() >> 5) * 67108864. +
static_cast<double>(rand_int32() >> 6)) * (1. / 9007199254740992.); }
private:
MTRand53(const MTRand53&); // copy constructor not defined
void operator=(const MTRand53&); // assignment operator not defined
};
#endif // MTRAND_H
**Errors generated by VC++:**
mtrand.cpp
d:mainmtrand.h(65) : error C2258: illegal pure syntax, must be '= 0'
d:mainmtrand.h(65) : error C2252: 'n' : pure specifier can only be
specified for functions
d:mainmtrand.h(65) : error C2258: illegal pure syntax, must be '= 0'
d:mainmtrand.h(65) : error C2252: 'm' : pure specifier can only be
specified for functions
d:mainmtrand.h(67) : error C2065: 'n' : undeclared identifier
d:mainmtrand.h(67) : error C2057: expected constant expression
D:Mainmtrand.cpp( : error C2057: expected constant expression
D:Mainmtrand.cpp( : error C2466: cannot allocate an array of constant
size 0
D:Mainmtrand.cpp(13) : error C2065: 'm' : undeclared identifier
D:Mainmtrand.cpp(15) : error C2374: 'i' : redefinition; multiple
initialization
D:Mainmtrand.cpp(13) : see declaration of 'i'
D:Mainmtrand.cpp(43) : error C2374: 'k' : redefinition; multiple
initialization
D:Mainmtrand.cpp(36) : see declaration of 'k'
Error executing cl.exe.
Main.exe - 11 error(s), 0 warning(s)
|
|
| Back to top |
|
 |
Christopher Benson-Manica Guest
|
Posted: Fri Feb 27, 2004 9:25 pm Post subject: Re: random number code |
|
|
Jason <jason.carney1 (AT) btinternet (DOT) com> spoke thus:
| Quote: | I need a way to use random numbers in c++. In my c++ project, when using
the mingw compiler I used a mersenne twister that is publicly available and
this did its job well. Now I have shelled out on VC++ 6.0 compiling that
same code is proving difficult. I am not too worried how I generate random
numbers in c++, as long as it is sufficiently random.
Can anybody help me out in getting what I want from VC++?
|
I don't know if it'll help you, but an ANSI C random number generator
was posted a few weeks ago to comp.lang.c. You may want to check that
out.
--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
|
|
| Back to top |
|
 |
Cy Edmunds Guest
|
Posted: Fri Feb 27, 2004 10:25 pm Post subject: Re: random number code |
|
|
"Jason" <jason.carney1 (AT) btinternet (DOT) com> wrote
| Quote: | Hi,
I need a way to use random numbers in c++. [snip]
|
You could try UVS. You can get it from my sig and it works on 6.0.
--
Cy
http://home.rochester.rr.com/cyhome/
|
|
| Back to top |
|
 |
Evan Carew Guest
|
Posted: Fri Feb 27, 2004 11:45 pm Post subject: Re: random number code |
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Jason,
Perhaps I'm missing something, but wouldn't rand() or srand() of
stdlib.h work? if you don't like that, you could always try Boost's
http://boost.org/libs/random/index.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFAP9acoo/Prlj9GScRAk/sAJ0V+F9/7RPiWbNnyOiOq7qZKvWEUQCfc9bt
L81DJIiu7WMg8uD/Bs5xrXg=
=4J93
-----END PGP SIGNATURE-----
|
|
| Back to top |
|
 |
Chris Theis Guest
|
Posted: Sat Feb 28, 2004 12:21 pm Post subject: Re: random number code |
|
|
"Evan Carew" <tempcarew (AT) pobox (DOT) com> wrote
| Quote: | -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Jason,
Perhaps I'm missing something, but wouldn't rand() or srand() of
stdlib.h work?
|
Ouch! Just a comment on the quality of "randomness" that rand() provides -
it is certainly not sufficient for applications where randomness (i.e., a
low grade of correlation) is required. Thus, it's good practice to stay away
from it.
That's one way to go!
Cheers
Chris
|
|
| Back to top |
|
 |
Chris Theis Guest
|
Posted: Sat Feb 28, 2004 12:28 pm Post subject: Re: random number code |
|
|
"Jason" <jason.carney1 (AT) btinternet (DOT) com> wrote
| Quote: | Hi,
I need a way to use random numbers in c++. In my c++ project, when using
the mingw compiler I used a mersenne twister that is publicly available
and
this did its job well. Now I have shelled out on VC++ 6.0 compiling that
same code is proving difficult. I am not too worried how I generate
random
numbers in c++, as long as it is sufficiently random.
Can anybody help me out in getting what I want from VC++?
|
Yes.
| Quote: |
If anybody wants the existing code along with errors generated by VC++
then
see below. Perhaps someone can explain what the problem is and how to fix
it. Sorry it is long.
On a separate point, as you might expect it is quite dismoralising to buy
something that promised to be able to compile ISO C++ and then to have
errors thrown at you from code that compiled fine before. I am not
talking
about just this code, as I am faced with rewriting an entire project to
fit
in with VC++.
|
Well the topic of ISO compiler compliance is a long and dirty road. If you
want to stick to MS then I'd suggest to use version 7.1 as 6.0 is quite
outdated and carries some serious legacies. (I think the compliance level
dates back to pre 1999, but don't pin me down on that!). However, the
problem actually is in your code and not with the compiler.
[SNIP]
| Quote: | unsigned long rand_int32(); // generate 32 bit random integer
private:
static const int n = 624, m = 397; // compile time constants
|
And here we go. You can't declare and initialize these variables within the
class in one statement. Move the initialization out of the class scope and
you're fine.
| Quote: | // the variables below are static (no duplicates can exist)
static unsigned long state[n]; // state vector array
|
Replace [n] with [624] as the initialization is not available at this point.
[SNIP]
And that's it. One thing which is really a compiler shortcoming is the
"supposed" redifinition of variables used as counters in a for loop, but
this can easily be fixed by removing the redundant declarations.
HTH
Chris
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Sat Feb 28, 2004 2:33 pm Post subject: Re: random number code |
|
|
Chris Theis wrote:
| Quote: |
Ouch! Just a comment on the quality of "randomness" that rand() provides -
it is certainly not sufficient for applications where randomness (i.e., a
low grade of correlation) is required. Thus, it's good practice to stay away
from it.
|
Really? Where in the standard did you find this requirement?
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
|
| Back to top |
|
 |
Cy Edmunds Guest
|
Posted: Sat Feb 28, 2004 5:31 pm Post subject: Re: random number code |
|
|
"Pete Becker" <petebecker (AT) acm (DOT) org> wrote
| Quote: | Chris Theis wrote:
Ouch! Just a comment on the quality of "randomness" that rand()
provides -
it is certainly not sufficient for applications where randomness (i.e.,
a
low grade of correlation) is required. Thus, it's good practice to stay
away
from it.
Really? Where in the standard did you find this requirement?
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
Good point, Pete. Based on the quality of rand() implementations out there,
one might well imagine that the standard had some such requirement as:
26.3.45.788.9 The rand() function shall have one or more of the following
properties:
26.3.45.788.9.1 Samples plotted as (x, y) pairs shall reveal a trendy
Herringbone pattern.
26.3.45.788.9.2 Any sample with a very small value shall be immediately
followed by another small value.
26.3.45.788.9.3 At least one duplicate value shall be found in the first few
hundred samples.
But as you say, such things are not actually required by the standard.
--
Cy
http://home.rochester.rr.com/cyhome/
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Sat Feb 28, 2004 6:20 pm Post subject: Re: random number code |
|
|
Cy Edmunds wrote:
| Quote: |
Good point, Pete. Based on the quality of rand() implementations out there,
one might well imagine that the standard had some such requirement as:
|
That is certainly the common wisdom, but in fact most random number
generators are pretty good.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
|
| Back to top |
|
 |
Jason Guest
|
Posted: Sat Feb 28, 2004 9:13 pm Post subject: Re: random number code |
|
|
"Chris Theis" <Christian.Theis (AT) nospam (DOT) cern.ch> wrote
| Quote: | Well the topic of ISO compiler compliance is a long and dirty road. If you
want to stick to MS then I'd suggest to use version 7.1 as 6.0 is quite
outdated and carries some serious legacies. (I think the compliance level
dates back to pre 1999, but don't pin me down on that!). However, the
problem actually is in your code and not with the compiler.
|
Thanks for the corrections Chris, great message. Clearly it is in my
interests for you to expand on the point regarding "serious legacies". The
money is spent if I resold the software I would be losing good money. I
only wanted something to compile my existing c++ code and to provide a user
interface for it. It has singularly failed to do the former, I have not
tested it on the latter point. Any websites where its problems are
documented or any advice you can offer? Thanks again.
| Quote: |
[SNIP]
unsigned long rand_int32(); // generate 32 bit random integer
private:
static const int n = 624, m = 397; // compile time constants
And here we go. You can't declare and initialize these variables within
the
class in one statement. Move the initialization out of the class scope and
you're fine.
// the variables below are static (no duplicates can exist)
static unsigned long state[n]; // state vector array
Replace [n] with [624] as the initialization is not available at this
point.
[SNIP]
And that's it. One thing which is really a compiler shortcoming is the
"supposed" redifinition of variables used as counters in a for loop, but
this can easily be fixed by removing the redundant declarations.
|
I am glad you fixed this because as indicated in other messages on here,
there is a view somewhere that it is poor practice to use rand and srand
when you require randomness in a serious way. This is due to the poor
quality of randomness. I have no idea whether what I have read has any
authority but that is why I sought alternatives.
|
|
| Back to top |
|
 |
Pete Becker Guest
|
Posted: Sat Feb 28, 2004 9:26 pm Post subject: Re: random number code |
|
|
Jason wrote:
| Quote: |
I am glad you fixed this because as indicated in other messages on here,
there is a view somewhere that it is poor practice to use rand and srand
when you require randomness in a serious way.
|
When you require randomness in a serious way it is poor practice to use
any random number generator until you have carefully analyzed its
properties.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
|
| Back to top |
|
 |
Jason Guest
|
Posted: Sun Feb 29, 2004 12:36 am Post subject: Re: random number code |
|
|
| Quote: | When you require randomness in a serious way it is poor practice to use
any random number generator until you have carefully analyzed its
properties.
|
Thanks for pointing out the obvious.
|
|
| Back to top |
|
 |
Chris Theis Guest
|
Posted: Mon Mar 01, 2004 1:20 pm Post subject: Re: random number code |
|
|
"Pete Becker" <petebecker (AT) acm (DOT) org> schrieb im Newsbeitrag
news:4040DBF1.D255E8CF (AT) acm (DOT) org...
| Quote: | Cy Edmunds wrote:
Good point, Pete. Based on the quality of rand() implementations out
there,
one might well imagine that the standard had some such requirement as:
That is certainly the common wisdom, but in fact most random number
generators are pretty good.
|
Hmm, then we have made quite a different experiences. Implementing and
performing Monte Carlo simulations I've come across many wrecked
implementations of such generators. However, one would have to elaborate on
what "good" means in the context of random numbers and I guess this would
lead way too far here.
Regards
Chris
|
|
| Back to top |
|
 |
Chris Theis Guest
|
Posted: Mon Mar 01, 2004 1:25 pm Post subject: Re: random number code |
|
|
"Jason" <jason.carney1 (AT) btinternet (DOT) com> schrieb im Newsbeitrag
news:c1r09k$enf$1 (AT) hercules (DOT) btinternet.com...
[SNIP]
| Quote: |
Thanks for the corrections Chris, great message. Clearly it is in my
interests for you to expand on the point regarding "serious legacies".
The
money is spent if I resold the software I would be losing good money.
I
only wanted something to compile my existing c++ code and to provide a
user
interface for it. It has singularly failed to do the former, I have not
tested it on the latter point. Any websites where its problems are
documented or any advice you can offer? Thanks again.
|
Sorry but I can't give you a website summing up all the shortcomings of VC
6.0. However, the support of templates (especially with regard to partial
specialization, nested templates, etc.) is quite poor. Thus, I'd recommend
to upgrade to version 7.1.
[SNIP]
| Quote: |
I am glad you fixed this because as indicated in other messages on here,
there is a view somewhere that it is poor practice to use rand and srand
when you require randomness in a serious way. This is due to the poor
quality of randomness. I have no idea whether what I have read has any
authority but that is why I sought alternatives.
|
If you need more in detail information about random numbers and the quality
of "randomness" IMHO the book by Donald Knuth (The Art of Computer
Programming,Volume 2) is the place to start with.
HTH
Chris
|
|
| Back to top |
|
 |
Claudio Puviani Guest
|
Posted: Mon Mar 01, 2004 3:26 pm Post subject: Re: random number code |
|
|
"Chris Theis" <Christian.Theis (AT) nospam (DOT) cern.ch> wrote
| Quote: | Hmm, then we have made quite a different experiences. Implementing and
performing Monte Carlo simulations I've come across many wrecked
implementations of such generators. However, one would have to elaborate on
what "good" means in the context of random numbers and I guess this would
lead way too far here.
|
It's important to realize that most Monte Carlo simulations "break" (or rather,
give skewed results) not because the pseudo-random number generator is
statistically faulty, but because its period is too short. If you had a
statistically "perfect" (passes all tests) pseudo-random number generator with a
period of 2^32 and you performed 2^40 calculations, you'd just be re-using the
same statistically "perfect" sequence of numbers 256 times. Put differently, a
statistically "perfect" distribution is no longer statistically "perfect" if
it's repeated.
Claudio Puviani
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|