免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
C/C++ 中生成特定范圍內(nèi)的隨機(jī)數(shù)

大家在寫 C/C++ 程序時(shí),難免會(huì)遇到要求獲取某個(gè)范圍內(nèi)的隨機(jī)數(shù),我查閱了一些資料后,總結(jié)如下。本文分兩部分,先介紹 C 語(yǔ)言中與隨機(jī)數(shù)相關(guān)的兩個(gè)函數(shù) srand 和 rand,后介紹 C++ 中的 random 庫(kù),每一部分最后會(huì)給出生成特定范圍內(nèi)的隨機(jī)數(shù)模板供參考。


1 C 語(yǔ)言中的 srand 和 rand


1.1 實(shí)現(xiàn)

下面是 VC 的實(shí)現(xiàn),GCC 的實(shí)現(xiàn)比 VC 的復(fù)雜,但基本原理是一樣的。
  1. #define RAND_MAX 32767  // in <stdlib.h>  
  2.   
  3. unsigned long _Randseed = 1;    // global seed  
  4.   
  5. void srand(unsigned int seed) {  
  6.     _Randseed = seed;  
  7. }  
  8.   
  9. int rand(void) {  
  10.     _Randseed = _Randseed * 1103515245 + 12345;  
  11.   
  12.     return ((unsigned int)(_Randseed >> 16) & RAND_MAX);  
  13. }  

第一次接觸 C 語(yǔ)言中的隨機(jī)數(shù)時(shí),很疑惑為什么有種子這個(gè)玩意,只提供一個(gè)產(chǎn)生隨機(jī)數(shù)的函數(shù)不就行了嗎,看了上面的源碼后,就明白了,因?yàn)?span style="color:#ff0000">計(jì)算機(jī)不能產(chǎn)生真正的隨機(jī)數(shù),只能靠數(shù)學(xué)的方法產(chǎn)生偽隨機(jī)數(shù)。srand 函數(shù)的作用是設(shè)置種子,如果不設(shè)置的話種子(上面的 _Randseed)則默認(rèn)初始是1,種子是全局變量。rand 的實(shí)現(xiàn)就跟數(shù)論有關(guān)了,上面的實(shí)現(xiàn)用的是線性同余法??梢钥吹剿姆祷刂捣秶?[0, RAND_MAX]。


1.2 time

既然計(jì)算機(jī)不能產(chǎn)生真正的隨機(jī)數(shù),那怎么才能使程序每次運(yùn)行的結(jié)果不同呢?總得有個(gè)隨機(jī)的東西,那就借助 time 這個(gè)函數(shù)產(chǎn)生種子,引入一個(gè)新東西又會(huì)帶來(lái)一些坑,我早年寫過(guò)這種程序:

  1. // 生成十個(gè)隨機(jī)數(shù)(錯(cuò)誤用法)  
  2. for (int i = 0; i < 10; ++i) {  
  3.     srand((unsigned int)time(NULL));  
  4.     printf("%d: %d\n", i, rand());  
  5. }  
它將產(chǎn)生10個(gè)相同的數(shù)。要解釋這個(gè)問(wèn)題,就得弄懂 time 這個(gè)函數(shù),它的函數(shù)原型如下:
  1. time_t time(time_t *timer);  

它返回“當(dāng)前時(shí)間”,這個(gè)“時(shí)間“的類型是 time_t,在 VC 中被 typedef 為 unsigned long,標(biāo)準(zhǔn)中只規(guī)定它是個(gè)算數(shù)類型,至于它是如何表示時(shí)間的未定義。一般是返回 UNIX 時(shí)間戳,定義為從格林威治時(shí)間1970年01月01日00時(shí)00分00秒起至現(xiàn)在的總秒數(shù)。上面的程序執(zhí)行時(shí)很快,在一秒內(nèi)完成循環(huán),所以它產(chǎn)生了相同的隨機(jī)數(shù)。


1.3 my rand

下面提供兩個(gè)生成隨機(jī)數(shù)的模板。

  1. int g_is_first = 1;  
  2.   
  3. /* 
  4. ** return a random integer in the interval 
  5. ** [a, b] 
  6. */  
  7. int uniform_int(int a, int b) {  
  8.     if (g_is_first) {  
  9.         g_is_first = 0;  
  10.         srand((unsigned int)time(NULL));  
  11.     }  
  12.   
  13.     return (int)((double)rand() / ((RAND_MAX + 1.0) / (b - a + 1.0)) + a);  
  14. }  
  15.   
  16. /* 
  17. ** return a random real in the interval 
  18. ** [a, b] (also [a, b)) 
  19. */  
  20. double uniform_real(double a, double b) {  
  21.     if (g_is_first) {  
  22.         g_is_first = 0;  
  23.         srand((unsigned int)time(NULL));  
  24.     }  
  25.   
  26.     return (double)rand() / ((double)RAND_MAX / (b - a)) + a;  
  27. }  
為了保證 srand 函數(shù)只執(zhí)行一次,這里用了全局標(biāo)志 g_is_first。其實(shí)最好在頭文件中定義接口,在源文件中實(shí)現(xiàn),這里為了使用方便就全放一起了。當(dāng)要求的隨機(jī)數(shù)范圍過(guò)大時(shí),uniform_int 和 uniform_real 貌似有 bug。


2 C++ 中的 random 庫(kù)


在 random 庫(kù)中有隨機(jī)數(shù)發(fā)生器(random engine/generator)和分布(distribution),它們的具體用法我就不在這說(shuō)了。我個(gè)人認(rèn)為 engine 存儲(chǔ)了種子,將 C 語(yǔ)言中的全局種子封裝起來(lái)了。uniform distribution 中只存儲(chǔ)了最大值和最小值(即平均分布的兩個(gè)參數(shù))。還有個(gè)真正的 engine 叫 std::random_device,它根據(jù)機(jī)器的各種實(shí)時(shí)參數(shù)產(chǎn)生隨機(jī)數(shù),標(biāo)準(zhǔn)規(guī)定它的實(shí)現(xiàn)是可選的,有的編譯器(如 MinGW)目前不支持,產(chǎn)生的還是偽隨機(jī)數(shù),不過(guò) VC 及 Linux 平臺(tái)上的 GCC 是支持的,下面的程序假設(shè)用戶的編譯器支持。
  1. /* 
  2. ** return a random integer in the interval [a, b] 
  3. */  
  4. int uniform_int(int a, int b) {  
  5.     static std::default_random_engine e{std::random_device{}()}; // avoid "Most vexing parse"  
  6.     static std::uniform_int_distribution<int> u;  
  7.   
  8.     return u(e, decltype(u)::param_type(a, b));  
  9. }  
  10.   
  11. /* 
  12. ** return a random real in the interval [a, b] (also [a, b)) 
  13. */  
  14. double uniform_real(double a, double b) {  
  15.     static std::default_random_engine e{std::random_device{}()};  
  16.     static std::uniform_real_distribution<double> u;  
  17.   
  18.     return u(e, decltype(u)::param_type(a, b));  
  19. }  
最后,還有個(gè)問(wèn)題沒(méi)搞懂:能否始終用 random_device 代替 default_random_engine ?它們的區(qū)別是什么?


本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C中的隨機(jī)數(shù)(媽的, 搞了我3個(gè)小時(shí))
用c語(yǔ)言產(chǎn)生隨機(jī)數(shù) - meizhe143的日志 - 網(wǎng)易博客
C++中產(chǎn)生隨機(jī)數(shù)
C++隨機(jī)數(shù)的用法
linux下真正的"偽隨機(jī)數(shù)"
C,C++隨機(jī)數(shù)產(chǎn)生
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服