#ifndef RAND_H #define RAND_H /////////////////////////////////////////////////////////////// // rand.h - generate uniformily distributed random // // ver 1.0 numbers in some interval. Template class // // generates either int or double numbers. // // // // Langauge: Visual C++, ver 6.0 // // Platform: Micron Dual Pentium Pro 200, Win NT 4.0 // // Application: ELE591/791 Project #2 prototype // // Author: Jim Fawcett, CST 2-187, Syracuse Univ. // // (315) 443-3948, fawcett@ecs.syr.edu // /////////////////////////////////////////////////////////////// /* Class Operations: ================= The rand class objects generate uniformily distributed integers or doubles in an interval specified in the generator's constructor call. Some care has been taken to make each new object generate percep- tively different number sequences. However, since the random number generator seed is derived from system time, constructions which lie within a millisecond of each other will have nearly the same values. For this reason it is advisable to make the random number generator object a static variable. Thus it will only be constructed once and will generate unique numbers each time called up to the period of the underlying random number generator provided by cstdlib::rand() function. Public Interface: ================= uniform gi(0,99); constructs a generator of ints for [0,99] uniform gd(0.0,1.0); constructs a generator of doubles for [0.0,1.0] void seed(long int s); allows user to supply a fixed seed so that the same sequence results every time the program is run double d = gd.gen(); generates a random double value if(event(p)) generate a true value with probability p { stuff } */ // /////////////////////////////////////////////////////////////// // Build Process // /////////////////////////////////////////////////////////////// // Required Files: // // rand.h, rand.cpp // // // // Compiler Command: // // testing rand: // // cl /GX /DTEST_RAND rand.cpp // // building application: // // cl /GX application.cpp rand.cpp // /////////////////////////////////////////////////////////////// /* Maintenance History: ==================== ver 1.0 : 20 Jul 1999 - first release ver 1.1 : 29 Jul 2000 - made seeding static to avoid initialization problems - see test stub in rand.cpp for examples of use. */ #include #include #include #include #include ///////////////////////////////////////////////////////////////////////////// // Seed class // // This class is used to seed (provide a start state for) the C Library // random number generator. We will use this as a private static member // of our uniform class, defined below, so that its instances will share // a common seed. That is, we want the generated random values to all // be drawn from the same sequence. The reason that we do this is that // if several generators are independently started in very close time // proximity they will have the same sequence values, which is usually // undesireable. // class Seed { public: Seed(); }; //----< Calculate seed >--------------------------------------- // - need to use large seed value for random number generator in // order to get a relatively long period between repeating values. // - need to generate quite different seed each time constructor is // called so numbers will be peceptually different for each new // generator. We accomplish this by multiplying the relatively // large count value by millisecond count of the system clock. // inline Seed::Seed() { unsigned int count = 654321; SYSTEMTIME st; GetSystemTime(&st); count *= st.wMilliseconds; // seed the random number generator using the volitile count and // system time which varies slowly, but with fine resolution, since // the time function returns number of seconds elapsed since midnight // Jan 1, 1970. // std::cout << "\n seeding with " << count << "\n"; srand((unsigned)time(NULL) + count); } template class uniform { public: uniform(T min, T max); void seed(long int s=0); T gen(); bool event(double prob); private: double scaleFactor; T _max,_min; // seed the c lib rand() generator only once static Seed _s; }; template Seed uniform::_s; // //----< constructor >------------------------------------------ template uniform::uniform(T min, T max) : _min(min), _max(max) { scaleFactor = double (max-min)/double(RAND_MAX); // set range of values } //----< give random number generator a specified seed >-------- // // call this function only if you want to get the same sequence // every time your program is run. This is useful primarily // for getting repeatable debugging runs. // template void uniform::seed(long int s) { unsigned int count = 654321; srand(s+count); } //----< generate a uniformily distributed random number >------ template T uniform::gen() { T n = rand()%(_max - _min + 1); return (n + _min); } //----< specialization of generate, above >-------------------- template <> double uniform::gen() { double d; while((d = static_cast((rand()*scaleFactor) + _min)) > _max) ; return d; } //----< generate an event with given probability >------------- // // event will return true with the given probability, otherwise false // template bool uniform::event(double probability) { uniform value(0.0, 1.0); double val = value.gen(); if(value.gen() <= probability) return true; return false; } #endif