⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 newran.cpp

📁 随机数发生器C++写的
💻 CPP
📖 第 1 页 / 共 3 页
字号:
   { Real r1 = rv1->Next(); Real r2 = rv2->Next(); return r1 + r2; }ExtReal AddedRandom::Mean() const { return rv1->Mean() + rv2->Mean() ; }ExtReal AddedRandom::Variance() const   { return rv1->Variance() + rv2->Variance() ; }Real SubtractedRandom::Next()   { Real r1 = rv1->Next(); Real r2 = rv2->Next(); return r1 - r2; }ExtReal SubtractedRandom::Mean() const { return rv1->Mean() - rv2->Mean() ; }ExtReal SubtractedRandom::Variance() const   { return rv1->Variance() + rv2->Variance() ; }Real MultipliedRandom::Next()   { Real r1 = rv1->Next(); Real r2 = rv2->Next(); return r1 * r2; }ExtReal MultipliedRandom::Mean() const { return rv1->Mean() * rv2->Mean() ; }ExtReal MultipliedRandom::Variance() const{   ExtReal e1 = square(rv1->Mean()); ExtReal e2 = square(rv2->Mean());   ExtReal v1 = rv1->Variance(); ExtReal v2 = rv2->Variance();   ExtReal r=v1*v2+v1*e2+e1*v2;   return r;}Real DividedRandom::Next()   { Real r1 = rv1->Next(); Real r2 = rv2->Next(); return r1 / r2; }void Random::load(int*,Real*,Random**)   { Throw(Logic_error("Newran: illegal combination")); }void SelectedRandom::load(int* i, Real* probs, Random** rvx){   probs[*i]=p; rvx[*i]=rv; (*i)++;   delete this;}Real SelectedRandom::Next()   { Throw(Logic_error("Newran: Next not defined")); return 0.0; }Real AddedSelectedRandom::Next()   { Throw(Logic_error("Newran: Next not defined")); return 0.0; }Real RepeatedRandom::Next()   { Real sum=0.0; for (int i=0; i<n; i++) sum += rv->Next(); return sum; }MixedRandom::MixedRandom(int nx, Real* probs, Random** rvx){   n = nx;   rv = new Random*[n]; if (!rv) ErrorNoSpace();   for (int i=0; i<n; i++) rv[i]=rvx[i];   Build(probs);}MixedRandom::MixedRandom(AddedSelectedRandom& sr){   n = sr.nelems();                       // number of terms;   Real* probs = new Real[n]; rv = new Random*[n];   if (!probs || !rv) ErrorNoSpace();   int i=0; sr.load(&i,probs,rv);   Build(probs); delete [] probs;}void MixedRandom::Build(Real* probs){   int i;   dg=new DiscreteGen(n,probs);   if (!dg) ErrorNoSpace();   mean=0.0; var=0.0;   for (i=0; i<n; i++) mean = mean + (rv[i])->Mean()*probs[i];   for (i=0; i<n; i++)   {      ExtReal sigsq=(rv[i])->Variance();      ExtReal mudif=(rv[i])->Mean()-mean;      var = var + (sigsq+square(mudif))*probs[i];   }}MixedRandom::~MixedRandom(){   for (int i=0; i<n; i++) rv[i]->tDelete();   delete dg; delete [] rv;}Real MixedRandom::Next()   { int i = (int)(dg->Next()); return (rv[i])->Next(); }int AddedSelectedRandom::nelems() const   { return rv1->nelems() + rv2->nelems(); }void AddedSelectedRandom::load(int* i, Real* probs, Random** rvx){   rv1->load(i, probs, rvx); rv2->load(i, probs, rvx);   delete this;}AddedSelectedRandom& operator+(SelectedRandom& rv1,   SelectedRandom& rv2){   AddedSelectedRandom* r = new AddedSelectedRandom(rv1, rv2);   if (!r) ErrorNoSpace(); return *r;}AddedSelectedRandom& operator+(AddedSelectedRandom& rv1,   SelectedRandom& rv2){   AddedSelectedRandom* r = new AddedSelectedRandom(rv1, rv2);   if (!r) ErrorNoSpace(); return *r;}AddedSelectedRandom& operator+(SelectedRandom& rv1,   AddedSelectedRandom& rv2){   AddedSelectedRandom* r = new AddedSelectedRandom(rv1, rv2);   if (!r) ErrorNoSpace(); return *r;}AddedSelectedRandom& operator+(AddedSelectedRandom& rv1,   AddedSelectedRandom& rv2){   AddedSelectedRandom* r = new AddedSelectedRandom(rv1, rv2);   if (!r) ErrorNoSpace(); return *r;}SelectedRandom& Random::operator()(double p){   SelectedRandom* r = new SelectedRandom(*this, p);   if (!r) ErrorNoSpace(); return *r;}// Identification routines for each class - may not work on all compilers?char* Random::Name()            { return "Random";           }char* Uniform::Name()           { return "Uniform";          }char* Constant::Name()          { return "Constant";         }char* PosGen::Name()            { return "PosGen";           }char* SymGen::Name()            { return "SymGen";           }char* AsymGen::Name()           { return "AsymGen";          }char* PosGenX::Name()           { return "PosGenX";          }char* SymGenX::Name()           { return "SymGenX";          }char* AsymGenX::Name()          { return "AsymGenX";         }char* Normal::Name()            { return "Normal";           }char* ChiSq::Name()             { return "ChiSq";            }char* Cauchy::Name()            { return "Cauchy";           }char* Exponential::Name()       { return "Exponential";      }char* Poisson::Name()           { return "Poisson";          }char* Binomial::Name()          { return "Binomial";         }char* NegativeBinomial::Name()  { return "NegativeBinomial"; }char* Gamma::Name()             { return "Gamma";            }char* Pareto::Name()            { return "Pareto";           }char* DiscreteGen::Name()       { return "DiscreteGen";      }char* SumRandom::Name()         { return "SumRandom";        }char* MixedRandom::Name()       { return "MixedRandom";      }// ********************** permutation generator ***************************void RandomPermutation::Next(int N, int M, int p[], int start){   // N = size of urn; M = number of draws   if (N < M) Throw(Logic_error("Newran: N < M in RandomPermutation"));   int i;   int* q = new int [N];   if (!q) ErrorNoSpace();   for (i = 0; i < N; i++) q[i] = start + i;   for (i = 0; i < M; i++)   {      int k = i + (int)(U.Next() * (N - i));       // uniform on i ... N-1      p[i] = q[k]; q[k] = q[i];                    // swap i and k terms                                                   // but put i-th term into p   }   delete [] q;}// from Sedgewickvoid ShellSortAscending(int* a, int N){   int h;   for (h = 1; h <= N / 9; h = 3*h + 1) {}   for (; h > 0; h /= 3) for (int i = h; i < N; ++i)   {      int v = a[i]; int j = i;      while (j>=h && a[j-h] > v) { a[j] = a[j-h]; j-= h; }      a[j] = v;   }}void RandomCombination::SortAscending(int n, int gm[]){   ShellSortAscending(gm, n);}//***************** Generators with variable parameters ********************VariPoisson::VariPoisson() : P100(100.0), P200(200.0) {}int VariPoisson::iNext_very_small(Real mu){   // mu is expected value of Poisson random number   // Efficient when mu is small   // generate a Poisson variable with mean mu   if (mu == 0) return 0;   Real t = exp(-mu); int k = 0; Real u = U.Next();   for (Real s = t; s < u; s += t) { ++k; t *= mu / k; }   return k;}int VariPoisson::iNext_small(Real mu){   // mu is expected value of Poisson random number   // Efficient when mu is reasonably small   // generate a Poisson variable with mean mu   // start iteration at mode   if (mu < 10) return iNext_very_small(mu);   int k_start = (int)mu;  Real u = U.Next();   Real t1 = exp(k_start * log(mu) - mu - ln_gamma(k_start+1));   if (t1 > u) return k_start;   int k1 = k_start; int k2 = k_start; Real t2 = t1; Real s = t1;   for(;;)   {      ++k1; t1 *= mu / k1; s += t1; if (s > u) return k1;      if (k2 > 0) { t2 *= k2 / mu; --k2; s += t2; if (s > u) return k2; }   }}int VariPoisson::iNext_large(Real mu){   // mu is expected value of Poisson random number   // reasonably accurate when mu is large, but should try to improve   // generate a Poisson variable with mean mu   // method is to start with normal variable X and use X with prob 1/3   // and X**2 with prob 2/3. In each case X has mean and variance to   // agree with Poisson rv after adjusting with Sheppard's correction   const Real sc = 1.0 / 12.0;        // Sheppard correction   int k;   if (U.Next() > 1.0 / 3.0)   {      Real musc = 0.5 * (mu - sc); Real meansq = sqrt(mu * mu - musc);      Real sigma = sqrt(musc / (mu + meansq));      k = (int)floor(square(N.Next() * sigma + sqrt(meansq)) + 0.5);   }   else k = (int)floor(N.Next() * sqrt(mu - sc) + mu + 0.5);   return k < 0 ? 0 : k;}int VariPoisson::iNext(Real mu){   if (mu <= 0)   {      if (mu == 0) return 0;      else Throw(Logic_error("Newran: illegal parameters"));   }   if (mu < 10) return iNext_very_small(mu);   else if (mu < 100) return iNext_small(mu);   else if (mu < 200)   {      // do in two statements so order of evaluation is preserved      int i = (int)P100.Next();      return i + iNext_small(mu - 100);   }   else if (mu < 300)   {      // do in two statements so order of evaluation is preserved      int i = (int)P200.Next();      return i + iNext_small(mu - 200);   }   else return iNext_large(mu);}VariBinomial::VariBinomial() {}int VariBinomial::iNext_very_small(int n, Real p){   // Efficient when n * p is small   // generate a Binomial variable with parameters n and p   Real q = 1 - p; if (q == 0) return n;   Real r = p / q; Real t = pow(q, n); Real s = t;   Real u = U.Next();   for (int k = 0; k <= n; ++k)   {      if (s >= u) return k;      t *= r * (Real)(n - k) / (Real)(k + 1);      s += t;   }   return 0;    // can happen only if we have round-off error}int VariBinomial::iNext_small(int n, Real p){   // Efficient when sqrt(n) * p is small   // Assume p <= 1/2   // same as small but start at mode   // generate a Binomial variable with parameters n and p   Real q = 1 - p; Real r = p / q; Real u = U.Next();   int k_start = (int)( (n * r) / (r + 1) );   Real t1 = exp( ln_gamma(n+1) - ln_gamma(k_start+1) - ln_gamma(n-k_start+1)      + k_start * log(p) + (n-k_start) * log(q) );   if (t1 >= u) return k_start;   Real t2 = t1; Real s = t1;   int k1 = k_start; int k2 = k_start;   for (;;)   {      t1 *= r * (Real)(n - k1) / (Real)(k1 + 1); ++k1; s += t1;      if (s >= u) return k1;      if (k2)      {         --k2; t2 *= (Real)(k2 + 1) / (Real)(n - k2) / r; s += t2;         if (s >= u) return k2;      }      else if (k1 == n) return 0;  // can happen only if we have round-off error   }}int VariBinomial::iNext(int n, Real p){   if (p > 0.5) return n - iNext(n, 1.0 - p);   if (n <= 0 || p <= 0)   {      if (n < 0 || p < 0) Throw(Logic_error("Newran: illegal parameters"));      else return 0;   }   Real mean = n * p;   if (mean <= 10) return iNext_very_small(n, p);   else if (mean <= 200) return iNext_small(n, p);   else return iNext_large(n,p);}// probably not sufficiently accurateint VariBinomial::iNext_large(int n, Real p){   const Real sc = 1.0 / 12.0;        // Sheppard correction   Real mean = n * p;   Real sd = sqrt(mean * (1.0 - p) - sc);   return (int)floor(N.Next() * sd + mean + 0.5);}Real VariLogNormal::Next(Real mean, Real sd){   // should have special version of log for small sd/mean   Real n_var = log(1 + square(sd / mean));   return mean * exp(N.Next() * sqrt(n_var) - 0.5 * n_var);}#ifdef use_namespace}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -