By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,190 Members | 1,412 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,190 IT Pros & Developers. It's quick & easy.

random number code

P: n/a
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 >> 18);
}

// 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:\main\mtrand.h(65) : error C2258: illegal pure syntax, must be '= 0'
d:\main\mtrand.h(65) : error C2252: 'n' : pure specifier can only be
specified for functions
d:\main\mtrand.h(65) : error C2258: illegal pure syntax, must be '= 0'
d:\main\mtrand.h(65) : error C2252: 'm' : pure specifier can only be
specified for functions
d:\main\mtrand.h(67) : error C2065: 'n' : undeclared identifier
d:\main\mtrand.h(67) : error C2057: expected constant expression
D:\Main\mtrand.cpp(8) : error C2057: expected constant expression
D:\Main\mtrand.cpp(8) : error C2466: cannot allocate an array of constant
size 0
D:\Main\mtrand.cpp(13) : error C2065: 'm' : undeclared identifier
D:\Main\mtrand.cpp(15) : error C2374: 'i' : redefinition; multiple
initialization
D:\Main\mtrand.cpp(13) : see declaration of 'i'
D:\Main\mtrand.cpp(43) : error C2374: 'k' : redefinition; multiple
initialization
D:\Main\mtrand.cpp(36) : see declaration of 'k'
Error executing cl.exe.

Main.exe - 11 error(s), 0 warning(s)


Jul 22 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a
Jason <ja***********@btinternet.com> spoke thus:
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.
Jul 22 '05 #2

P: n/a
"Jason" <ja***********@btinternet.com> wrote in message
news:c1**********@hercules.btinternet.com...
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/
Jul 22 '05 #3

P: n/a
-----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-----
Jul 22 '05 #4

P: n/a

"Evan Carew" <te*******@pobox.com> wrote in message
news:10*************@corp.supernews.com...
-----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.
if you don't like that, you could always try Boost's
http://boost.org/libs/random/index.html


That's one way to go!

Cheers
Chris
Jul 22 '05 #5

P: n/a

"Jason" <ja***********@btinternet.com> wrote in message
news:c1**********@hercules.btinternet.com...
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.

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] 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.

HTH
Chris
Jul 22 '05 #6

P: n/a
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)
Jul 22 '05 #7

P: n/a
"Pete Becker" <pe********@acm.org> wrote in message
news:40***************@acm.org...
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/
Jul 22 '05 #8

P: n/a
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.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #9

P: n/a

"Chris Theis" <Ch*************@nospam.cern.ch> wrote in message
news:c1**********@sunnews.cern.ch...
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.

[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.
HTH
Chris

Jul 22 '05 #10

P: n/a
Jason wrote:

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)
Jul 22 '05 #11

P: n/a
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.

Jul 22 '05 #12

P: n/a

"Pete Becker" <pe********@acm.org> schrieb im Newsbeitrag
news:40***************@acm.org...
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
Jul 22 '05 #13

P: n/a

"Jason" <ja***********@btinternet.com> schrieb im Newsbeitrag
news:c1**********@hercules.btinternet.com...
[SNIP]

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]
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
Jul 22 '05 #14

P: n/a
"Chris Theis" <Ch*************@nospam.cern.ch> wrote
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
Jul 22 '05 #15

P: n/a
On Sat, 28 Feb 2004 21:13:24 +0000 (UTC), Jason wrote:
"Chris Theis" <Ch*************@nospam.cern.ch> wrote in message
news:c1**********@sunnews.cern.ch...
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.


Did you get the answer you were looking for from the rest of Chris' message
(which I have left in below)? It sounds from this paragraph like you might
not have grasped that the problem VC++ has in compiling your old code is
that your old code is not actually ANSI compliant. VC++, and all other
compilers, should refuse to compile it. Put another way, "successful"
compilation of your code should be considered a compiler bug.
Any websites where its problems are
documented or any advice you can offer? Thanks again.


http://msdn.microsoft.com/library/en...sInVisualC.asp
has a list of things that were improved in VC++7.1 (aka .NET 2003). As I
understand it, the move from 6.x to 7.0 was essentially a facelift, they
are very similar in terms of standard compliance. 7.0 to 7.1 was where
most of the standards issues were addressed.

It looks like a list of compliance issues in version 6.x or 7.0 is at
http://www.microsoft.com/japan/msdn/...sInVisualC.asp
Despite the URL, very little of this page is actually in Japanese.
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.


That is a highly unfortunate side effect. Sucks to have that 624 repeated
in two places; it's almost sure to lead to an error when one is changed and
the other is missed. Perhaps better to use
static std::vector<unsigned long> state;
and then
state.resize(n);
in the constructor?

--
Greg Schmidt gr***@trawna.com
Trawna Publications http://www.trawna.com/
Jul 22 '05 #16

P: n/a
Greg Schmidt wrote:
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.


That is a highly unfortunate side effect. Sucks to have that 624
repeated
in two places; it's almost sure to lead to an error when one is
changed and
the other is missed. Perhaps better to use
static std::vector<unsigned long> state;
and then
state.resize(n);
in the constructor?


Instead of duplicating the 624 with
static const int n = 624, m = 397;
static unsigned long state[624];
you could write
enum {n = 624, m = 397};
static unsigned long state[n];

--
Regards,

Joe Hotchkiss,
http://joe.hotchkiss.com

XXXXXXXXXXXXXXXXXXXXXXXXX
X joe.hotchkiss X
X at baesystems.com X
XXXXXXXXXXXXXXXXXXXXXXXXX

Jul 22 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.