Sign in to follow this  

Boost Random Number Generators

This topic is 3933 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I found that Boost has a non-deterministic RNG class, but it's syntax and utilization are eluding me. I'm attempting to write a wrapper class that has functions that return the dice rolls for an n-sided die, but I keep getting unresolved externals when I attempt to create or use a boost::random_device.
//Class Definition
class Dice_Bag {
   boost::random_device RNG;
   
public:
   int Roll_d3();
   int Roll_d4();
   int Roll_d6();
   //etc.
private:
   int Roll_die(int);
};

int Dice_Bag::Roll_die(int sides) {
   return (RNG()%sides + 1);
}

...is my current attempt. I receive the following error when attempting to link:
Quote:
Dice_Bag.obj : error LNK2019: unresolved external symbol "public: unsigned int __thiscall boost::random_device::operator()(void)" (??Rrandom_device@boost@@QAEIXZ) referenced in function "private: int __thiscall Dice_Bag::Roll_Die(int)" (?Roll_Die@Dice_Bag@@AAEHH@Z)
Where is my syntax going wrong? Other of the boost number generators are placed inside a distributor (like mt19937) and I've gotten that to work wonderfully; I don't want deterministic behavior if I can help it. Does boost::random_device need a distributor as well? Any guidance would be greatly appreciated. Thank you!

Share this post


Link to post
Share on other sites
Your syntax isn't wrong. There's just no implementation of the () operator for the class. Most of the functionality of boost is included in the header files, but not always. In this case you'll see that some of the methods aren't implemented. This means you need to probably link to the library file for your particular compiler. This makes sense: the non-deterministic number generator is entirely dependent on the environment. One may not even exist on some computers. Link to the library. If you don't have the library, create one. If you don't know how, use this.
EDIT:
Yup, here's the file if you're curious.

Share this post


Link to post
Share on other sites
The non-deterministic RNG is not available on all platforms. In the boost libraries, it seems to only be implemented for linux using /dev/urandom by default.

If you want it to work on other platforms, you will have to implement random_device yourself.


jfl

Share this post


Link to post
Share on other sites
[quote]Original post by hereticprophecy

int Dice_Bag::Roll_die(int sides) {
return (RNG()%sides + 1);
}



[/quote]

I'm told using % like that for generating random values is a bad idea because it "favors the low bits". I'm not too sure how that works exactly, but the people who brought this to much attention are much smarter than me.

EDIT: Hmm. Seems you're not allowed to quote source boxes

Share this post


Link to post
Share on other sites
It favors the low numbers. Imagine if you RNG() returned a number 0..15, then you used RNG()%10, then the numbers 0..5 would turn up twice as much as the numbers 6..9

In practice it's not much of a concern since RNG() returns a larger range, but if it is, then the standard way of fixing it is to use % with a number that is a factor of the upper limit of RND() and bigger that the range you want (usually picking a power of 2) and use that to repick random numbers until you get one that falls in the range you want.

Share this post


Link to post
Share on other sites
Quote:
Original post by nobodynews
Your syntax isn't wrong. There's just no implementation of the () operator for the class. Most of the functionality of boost is included in the header files, but not always. In this case you'll see that some of the methods aren't implemented. This means you need to probably link to the library file for your particular compiler. This makes sense: the non-deterministic number generator is entirely dependent on the environment. One may not even exist on some computers. Link to the library. If you don't have the library, create one. If you don't know how, use this.
EDIT:
Yup, here's the file if you're curious.


I used the installed prior to attempting this (I had located the .cpp file last night but just figured it was linked automatically) but I'm not sure if I'm telling VC++ to look in the proper directories. Do I point libraries, executables, and includes toward the boot_1_33_1 directory or do they point at more specific folders? Or am I missing the point of your post entirely?

Share this post


Link to post
Share on other sites
Quote:
Original post by hereticprophecy
I used the installed prior to attempting this (I had located the .cpp file last night but just figured it was linked automatically) but I'm not sure if I'm telling VC++ to look in the proper directories. Do I point libraries, executables, and includes toward the boot_1_33_1 directory or do they point at more specific folders? Or am I missing the point of your post entirely?


I took another look at the header file and saw that it wasn't just operator() that didn't have an implementation, it was also the constructor, destructor, and a method called entropy. If the only thing giving you a problem is operator() then it probably isn't a problem with the location of your lib files. Because if it were, then you'd have four linker errors. In which case I don't have a clue why it's giving you a problem. Sorry. With that said, I'm not sure there IS a library file for random_device. I decided to test it out and I had to add the file I linked above directly to my project. But then, maybe MY locations are wrong.

The point is moot as this random number generator only works on linux as is. You'd have to figure out how to get chaotic information from another source in windows. And I don't know anything about that. Sorry again.

Share this post


Link to post
Share on other sites
On Windows, the equivalent to /dev/random is the CryptGenRandom() function.

Here's some basic C++ source (adapted from one of my projects).


#include <wincrypt.h>
HCRYPTPROV g_hCrypt;

bool my_random_init();
void my_random_shutdown();
void get_random_bytes(int size,char* buf);
char get_random_byte();
int get_random_int();

bool my_random_init()
{
//Init CryptoAPI for random generation
if(!CryptAcquireContext(&g_hCrypt,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT))
{
//Something went wrong, return error
return false;
}
else
return true;
}

void my_random_shutdown()
{
//Clean up CryptoAPI
CryptReleaseContext(g_hCrypt,0);
}

void get_random_bytes(int size,char* buf)
{
//Fill buf with random bytes ranging from 0x00 to 0xFF
CryptGenRandom(g_hCrypt,size,(unsigned char*)buf);
}

char get_random_byte()
{
//Return a single random byte from 0x00 to 0xFF
char ret;
get_random_bytes(sizeof(ret),&ret);
return ret;
}

int get_random_int()
{
//Return a random integer from 0 to INT_MAX
int ret;
get_random_bytes(sizeof(ret),(char*)&ret);
}


Share this post


Link to post
Share on other sites
I've come across another set of problems that I don't understand. I've rewritten my Dice_Bag class using the pseudo-random number generator boost::mt19937, uniform distribution boost::uniform_int<>, and boost::variate_generator<> as follows...


#include <boost/random.hpp>

class Dice_Bag {
boost::mt19937 rng;
boost::uniform_int<> d3(1,3);
boost::variate_generator<boost::mt19937&,boost::uniform_int<> >
Cast_d3(rng,d3);
};



This was all fine and dandy when I tested it in main(), but after moving into in a class, I get the following two syntax errors of all things:

Quote:

\My Documents\C++ Projects\RPG Engine\RPG Engine\Dice_Bag.h(5) : error C2059: syntax error : 'constant'
\My Documents\C++ Projects\RPG Engine\RPG Engine\Dice_Bag.h(7) : error C2061: syntax error : identifier 'rng'


Must these be initialized in a function?

Share this post


Link to post
Share on other sites
You can't inline initialize a member variable like that in C++. You want something like:

class Dice_Bag {
boost::mt19937 rng;
boost::uniform_int<> d3;
boost::variate_generator<boost::mt19937&,boost::uniform_int<> > Cast_d3;

Dice_Bag() : d3(1,3), Cast_d3(rng,d3) {}
};




jfl.

Share this post


Link to post
Share on other sites

This topic is 3933 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this