日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

c语言同余法随机数,线性同余法取随机数

發布時間:2024/8/1 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言同余法随机数,线性同余法取随机数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線性同余法求偽隨機數,Linear-Congruential: (a * x + c) % m, a > 0, m > 0, m % a < m / a.

首先,說明一下取隨機數一般會用rand函數,取time.h文件中的clock()作為種子,產生我們需要的隨機數

#include #include //srand()、rand()

#include //time();

int main() {

int n;

srand((unsigned)time(NULL)); //設置隨機數種子

for (int i= 0; i< 10; i++) {

n = (rand() % 10) + 1 ;//產生1~10的隨機數

//rand()產生的是一個很大的數,對其求余就可以達到限定范圍的目的

printf("%d ", n);

}

return 0;

}

但是如果我們產生隨機數種子的周期小于1s,那么就會產生一系列相同的隨機數。總而言之,當產生隨機數的周期非常非常小時,用已無法滿足這一需求。因此,我們采用線性同余法,也就是較為簡便的方法,那就是用現有的隨機數種子來產生新的種子,也就是Linear-Congruential generator(線性同余數發生器)。

它是根據遞歸公式:

seed = (a*seed) mod m;

or

seed = (a*seed + c) mod m;這條公式需要滿足:

a, m為正整數,m> a, m> seed;

它產生的隨機數是以m為周期的,一般我們以2^32- 1為周期,a又不能取太大,所以為了避免取模溢出,

我們用一種方法解決:

Schrage’s Method Revealed算法,將公式形式變換,避免了溢出。

x = (a*x) mod m

= a*(x mod Q) - R*[xi/Q];

if (x > 0) result_seed = x;

else result_seed = x + m;具體實現:

random_my.h文件

namespace RAND_GEN {

class mod_my {

public:

long long m, a, c;

mod_my(long long _m, long long _a, long long _c) : m(_m), a(_a), c(_c) {}

// General case for x = (ax + c) mod m -- use Schrage's algorithm

// to avoid integer overflow.

// (ax + c) mod m can be rewritten as:

// a(x mod q) - r(x / q) if >= 0

// a(x mod q) - r(x / q) otherwise

// where: q = m / a , r = m mod a

//

// Preconditions: a > 0, m > 0.

//

// Note: only works correctly for m % a < m / a.

long long calc(long long x) {

if (a == 1) {

x %= m;

} else {

long long q = m / a;

long long r = m % a;

long long t1 = a * (x % q);

long long t2 = r * (x / q);

if (t1 >= t2) x = t1 - t2;

else x = m - t2 + t1;

}

if (c != 0) {

const long long d = m - x;

if (d > c) x += c;

else x = c - d;

}

return x;

}

};

class linear_congruential_engine_my {

public:

long long multiplier, increment, modulus;

unsigned long long default_seed_my, seed_my;

mod_my mod_temp;

linear_congruential_engine_my()

: multiplier(16807), increment(1), modulus(2147483647)

, default_seed_my(1u), mod_temp(modulus, multiplier, increment)

{ seed(default_seed_my); }

linear_congruential_engine_my(long long _m, long long _a,

long long _c, long long _s)

: multiplier(_a), increment(_c), modulus(_m)

, default_seed_my(_s), mod_temp(modulus, multiplier, increment)

{ seed(default_seed_my); }

void seed(unsigned long long s)

{ seed_my = s; }

long long min()

{ return increment == 0u ? 1u : 0u; }

long long max()

{ return modulus - 1u; }

void discard(unsigned long long z)

{ for (; z != 0ULL; --z) (*this)(); }

long long operator()() {

seed_my = mod_temp.calc(seed_my);

return seed_my;

}

};

}main.cpp

#include #include "random_my.h"

using namespace std;

using namespace RAND_GEN;

void test_calc() {

mod_my mod_1(9223372036854775807, 16807, 1);

if (mod_1.calc(9223372036854775) != 7443261233741790514 ||

mod_1.calc(922337203685477580) != 6456360425798331301 ||

mod_1.calc(9223372036852222220) != 9223371993936639099 ||

mod_1.calc(922337203685473330) != 6456360425726901551 ||

mod_1.calc(9223372022254775806) != 9223126654654759001)

cout << "Your calc() is wrong.\n";

else cout << "Pass all tests for calc().\n";

}

void test_engin() {

linear_congruential_engine_my lce;

int count = 1000;

int num[1001] = {0};

while (count--) num[lce()%5]++;

if (num[0] != 216 || num[1] != 190 ||

num[2] != 203 || num[3] != 216 ||

num[4] != 175) {

cout << "Your engin class is wrong in generator.\n";

return;

} else if (lce.min() != (lce.increment == 0u ? 1u : 0u)) {

cout << "Your engin class is wrong in min().\n";

return;

} else if (lce.max() != (lce.modulus - 1u)) {

cout << "Your engin class is wrong in max().\n";

return;

}

else cout << "Pass all tests for class engin.\n";

}

void hard_test() {

long long m, a, c, n, num[5] = {0};

unsigned long long s;

unsigned long long discard_n;

cin >> m >> a >> c >> s;

mod_my mod_1(m, a, c);

for (int i = 0; i < 5; i++) {

cin >> n;

cout << "(MOD CALC) ";

cout << n << ": " << mod_1.calc(n) << endl;

}

linear_congruential_engine_my lce(m, a, c, s);

cin >> discard_n;

lce.discard(discard_n);

cin >> n;

while (n--) num[lce()%5]++;

for (int i = 0; i < 5; i++) {

cout << "(ENGIN) ";

cout << i << ": " << num[i] << endl;

}

}

int main() {

int t;

cin >> t;

if (t == 0) {

test_calc();

test_engin();

} else {

hard_test();

}

return 0;

}

總結

以上是生活随笔為你收集整理的c语言同余法随机数,线性同余法取随机数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。