亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

python學(xué)習(xí)筆記 --- 隨機數(shù)進階

cppowboy / 1470人閱讀

摘要:返回非負(fù)隨機數(shù)大于或等于零且小于的位帶符號整數(shù)。返回一個指定范圍內(nèi)的隨機數(shù)返回的隨機數(shù)的下界隨機數(shù)可取該下界值。其中參數(shù)是下限,參數(shù)是上限,生成的隨機數(shù)。如,結(jié)果相當(dāng)于從序列中獲取一個隨機數(shù)。

你真的懂隨機數(shù)?

Author : Jasper Yang
School : Bupt

Q:為什么要寫這篇文章?
A:因為我發(fā)現(xiàn)在最近的科學(xué)計算中,常常遇到隨機數(shù),所有的隨機數(shù)都是基于0,1隨機,而這個0,1隨機怎么實現(xiàn)呢?下面我會娓娓道來~

這篇文章不同于網(wǎng)路上的雜散的技術(shù)文,我是針對 random 這么一個論題展開調(diào)研最后將所有相關(guān)的知識進行整理敘述,希望每個人看完都可以得到小小的提升~

& 什么是隨機數(shù)

隨機數(shù):數(shù)學(xué)上產(chǎn)生的都是偽隨機數(shù),真正的隨機數(shù)使用物理方法產(chǎn)生的

隨機數(shù)種子:隨機數(shù)的產(chǎn)生是由算術(shù)規(guī)則產(chǎn)生的,在c++中,srand(seed)的隨機數(shù)種子不同,rand()的隨機數(shù)值就不同,倘若每次的隨機數(shù)種子一樣,則rand()的值就一樣。所以要產(chǎn)生隨機數(shù),則srand(seed)的隨機數(shù)種子必須也要隨機的。在 python 中就是 random.seed()來設(shè)置種子。

下面我講的隨機數(shù)不僅僅講隨機數(shù)生成的原理,也會講在python中以及在c++中怎么去實現(xiàn),當(dāng)然,大部分資料也都是網(wǎng)上找的,我只是做了一個整理匯總,并用自己的語言加以敘述。

& 隨機數(shù)的原理

這里我看了一篇博客,由于這篇博客是那個博主轉(zhuǎn)的,但是該博主并沒有表明是從哪里轉(zhuǎn)來的,我就不po出鏈接了,大家往下看~

有位朋友問那博主關(guān)于一段程序的錯誤。

C/C++ code
for (int i =0;i< n;++i)
{
    srand((unsigned)time( NULL )); 
    int r = rand()%100;
    cout << r << ",";
}

這里很明顯他是想輸出一串小于100的隨機的數(shù)列.可是運行結(jié)果輸出的卻是類似 97,97,97,97,....97,30,30,30,30,30,30,30,30,30,30,30,30,....,27,27,27,27,27,27,....的序列.很明顯這樣完全看不出有任何的隨機性.這是由于他對C的rand函數(shù)不理解導(dǎo)致的錯誤用法.而這兩天逛C#區(qū)我也同樣看到了幾個類似的錯誤用法(C和C#的rand從大體的原理上差不多).想想自己初學(xué)的時候類似的錯誤犯得也不少.所以自己下去查了寫資料總結(jié)了在隨機數(shù)使用上的一些錯誤的用法.希望能對初學(xué)者有所幫助。

現(xiàn)在各種語言中的隨機數(shù)產(chǎn)生函數(shù)所產(chǎn)生的"隨機數(shù)",實際上被稱之為"偽隨機數(shù)".可以將
整個隨機數(shù)函數(shù)看做這樣一個表達式:

$$A = R(s)$$

其中R是隨機函數(shù),s是種子.A是一個數(shù)列.即對于任意一個種子s,經(jīng)過R的計算后,總有一個確定的數(shù)列A與之對應(yīng).而當(dāng)在C#里調(diào)用var rnd = new Random (s)或在C里調(diào)用srand(s)實質(zhì)上所做工作之一就是設(shè)定這個種子.而rnd.Next();或rand()只不過是在A上取下一個元素而已.當(dāng)然實際的實現(xiàn)不可能事先計算一個數(shù)列A,所以rand()相當(dāng)于由s計算出下一個數(shù)字s",然后將s"作為新的種子賦值給s,最后將s"作為結(jié)果返回。

往細了講,就是這樣。

如果約定:$a_1=f(seed),a_{n+1}=f(an)$
那你可以行到一個序列:$a_1,a_2,a_3...a_n$,那么要制作一個偽隨機函數(shù)rand,只需要讓它每調(diào)用一次就返回序列的下一個元素就行。

下面是兩種常見的錯誤做法

C# code
for (int i=0;i

這樣,每次使用Random,都去申請了一個變量rnd,然后才用這個變量去找隨機數(shù)(rnd.Next())。這樣其實就是在隨機數(shù)的序列中總是在找第一個。這樣下來,第一個數(shù)肯定是固定的,就不存在什么隨機數(shù)了。

第二種情況更加常見。

C# code
for (int i=0;i

之前的第一種情況使用了一個固定的常數(shù)s來做種子,這里選用了系統(tǒng)時間做種子,想要達到隨機的效果,但是得到的結(jié)果往往就會是和博主那位朋友一樣的結(jié)果97,97,97,97,....97,30,30,30,30,30,30,30,30,30,30,30,30,....,27,27,27,27,27,27,.... 。

這是因為Windows系統(tǒng)時鐘的更新頻率大概在10ms左右.而這個for循環(huán)的執(zhí)行顯然要快
得多.于是在一段執(zhí)行時間內(nèi)Environment.TickCount (Random的默認(rèn)種子)或是C的time函數(shù)返回的都是同一個值.從而導(dǎo)致rnd.Next在一段時間內(nèi)返回一個常數(shù)。

所以正確的做法應(yīng)該是把種子移出循環(huán)之外。

C# code
var rnd = new Random ();//用系統(tǒng)時間作為種子
for (int i=0;i

各種庫中是怎么實現(xiàn)隨機數(shù)呢?
在 Linux 下實現(xiàn)的方式類似如下

static unsigned long next = 1;

/* RAND_MAX assumed to be 32767 */
int myrand(void) {
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % 32768);
}

void mysrand(unsigned seed) {
    next = seed;
}

myrand、mysrand分別對應(yīng)rand和srand,但實際的rand實現(xiàn)會復(fù)雜一些。

下面是這位博主實現(xiàn)的方式,其實挺簡單的,我們每個人都可以實現(xiàn)一種自己想要的隨機數(shù)方式加到自己的私有庫中~

*
 * Copyright (c) 2008 Microsoft::Tsorgy.Utils, Reserved.
 * 
 * Filename:    @(#)Random.cs
 * Create by:   TsOrgY
 * Email:       tsorgy@gmail.com
 * Date:        2008/12/27 15:01:40
 * 
 * Classname:   Random
 * Description: 一種能夠產(chǎn)生滿足某些隨機性統(tǒng)計要求的數(shù)字序列的設(shè)備.
 *              
 */
using System;
using System.Runtime.InteropServices;
namespace Tsorgy.Utils {
    /// 
    /// 表示偽隨機數(shù)生成器,一種能夠產(chǎn)生滿足某些隨機性統(tǒng)計要求的數(shù)字序列的設(shè)備.
    /// 
    [Serializable]
    [ComVisible(true)]
    public class Random {
        private int inext;
        private int inextp;
        private const int MBIG = 0x7fffffff;
        private const int MSEED = 0x9a4ec86;
        private const int MZ = 0;
        private int[] SeedArray;
        /// 
        /// 使用與時間相關(guān)的默認(rèn)種子值,初始化 Random 類的新實例.
        /// 
        public Random()
            : this(Environment.TickCount) {
        }
        /// 
        /// 使用指定的種子值初始化 System.Random 類的新實例.
        /// 
        /// 用來計算偽隨機數(shù)序列起始值的數(shù)字。如果指定的是負(fù)數(shù),則使用其絕對值。
        /// Seed 為 System.Int32.MinValue,在計算其絕對值時會導(dǎo)致溢出。
        public Random(int Seed) {
            this.SeedArray = new int[0x38];
            int num2 = 0x9a4ec86 - Math.Abs(Seed);
            this.SeedArray[0x37] = num2;
            int num3 = 1;
            for (int i = 1; i < 0x37; i++) {
                int index = (0x15 * i) % 0x37;
                this.SeedArray[index] = num3;
                num3 = num2 - num3;
                if (num3 < 0) {
                    num3 += 0x7fffffff;
                }
                num2 = this.SeedArray[index];
            }
            for (int j = 1; j < 5; j++) {
                for (int k = 1; k < 0x38; k++) {
                    this.SeedArray[k] -= this.SeedArray[1 + ((k + 30) % 0x37)];
                    if (this.SeedArray[k] < 0) {
                        this.SeedArray[k] += 0x7fffffff;
                    }
                }
            }
            this.inext = 0;
            this.inextp = 0x15;
            Seed = 1;
        }
        private double GetSampleForLargeRange() {
            int num = this.InternalSample();
            if ((((this.InternalSample() % 2) == 0) ? 1 : 0) != 0) {
                num = -num;
            }
            double num2 = num;
            num2 += 2147483646.0;
            return (num2 / 4294967293);
        }
        private int InternalSample() {
            int inext = this.inext;
            int inextp = this.inextp;
            if (++inext >= 0x38) {
                inext = 1;
            }
            if (++inextp >= 0x38) {
                inextp = 1;
            }
            int num = this.SeedArray[inext] - this.SeedArray[inextp];
            if (num < 0) {
                num += 0x7fffffff;
            }
            this.SeedArray[inext] = num;
            this.inext = inext;
            this.inextp = inextp;
            return num;
        }
        /// 
        /// 返回非負(fù)隨機數(shù).
        /// 
        /// 大于或等于零且小于 System.Int32.MaxValue 的 32 位帶符號整數(shù)。
        public virtual int Next() {
            return this.InternalSample();
        }
        /// 
        /// 返回一個小于所指定最大值的非負(fù)隨機數(shù).
        /// 
        /// 要生成的隨機數(shù)的上界(隨機數(shù)不能取該上界值)。maxValue 必須大于或等于零。
        /// 大于或等于零且小于 maxValue 的 32 位帶符號整數(shù),即:返回的值范圍包括零但不包括 maxValue。
        /// maxValue 小于零。
        public virtual int Next(int maxValue) {
            if (maxValue < 0) {
                throw new ArgumentOutOfRangeException("maxValue", string.Format(""{0}" must be greater than zero.", maxValue));
            }
            return (int) (this.Sample() * maxValue);
        }
        /// 
        /// 返回一個指定范圍內(nèi)的隨機數(shù).
        /// 
        /// 返回的隨機數(shù)的下界(隨機數(shù)可取該下界值)。
        /// 返回的隨機數(shù)的上界(隨機數(shù)不能取該上界值)。maxValue 必須大于或等于 minValue。
        /// 一個大于或等于 minValue 且小于 maxValue 的 32 位帶符號整數(shù),即:返回的值范圍包括 minValue 但不包括 maxValue。如果minValue 等于 maxValue,則返回 minValue。
        /// minValue 大于 maxValue。
        public virtual int Next(int minValue, int maxValue) {
            if (minValue > maxValue) {
                throw new ArgumentOutOfRangeException("minValue", string.Format(""{0}" cannot be greater than {1}.", minValue, maxValue));
            }
            long num = maxValue - minValue;
            if (num <= 0x7fffffffL) {
                return (((int) (this.Sample() * num)) + minValue);
            }
            return (((int) ((long) (this.GetSampleForLargeRange() * num))) + minValue);
        }
        /// 
        /// 用隨機數(shù)填充指定字節(jié)數(shù)組的元素.
        /// 
        /// 包含隨機數(shù)的字節(jié)數(shù)組。
        /// buffer 為 null。
        public virtual void NextBytes(byte[] buffer) {
            if (buffer == null) {
                throw new ArgumentNullException("buffer");
            }
            for (int i = 0; i < buffer.Length; i++) {
                buffer[i] = (byte) (this.InternalSample() % 0x100);
            }
        }
        /// 
        /// 返回一個介于 0.0 和 1.0 之間的隨機數(shù).
        /// 
        /// 大于或等于 0.0 而小于 1.0 的雙精度浮點數(shù)字。
        public virtual double NextDouble() {
            return this.Sample();
        }
        /// 
        /// 返回一個介于 0.0 和 1.0 之間的隨機數(shù).
        /// 
        /// 大于或等于 0.0 而小于 1.0 的雙精度浮點數(shù)字。
        protected virtual double Sample() {
            return (this.InternalSample() * 4.6566128752457969E-10);
        }
    }
}

這里我要另外提到一個大家聽到了很多次的東西 ------------> 線性同余法

這也是實現(xiàn)隨機數(shù)的一種方式

線性同余方法(LCG)

它的遞歸公式:

$$N_{j+1} = (A * N_j +B) (mod M)$$

其中A,B,M是產(chǎn)生器設(shè)定的常數(shù)。

LCG的周期最大為M,但大部分情況都會少于M。要令LCG達到最大周期,應(yīng)符合以下條件:

B,M互質(zhì)

M的所有質(zhì)因子的積能整除A-1

若M是4的倍數(shù),A-1也是

A,B,$N_0$都比M小

A,B是正整數(shù)

最后生成的就是一個 <$N_i$> 序列,這個序列應(yīng)該滿足下面的幾個條件。

這個函數(shù)應(yīng)該是一個完整周期的產(chǎn)生函數(shù)。也就是說,這個函數(shù)應(yīng)該在重復(fù)之前產(chǎn)生出0 到m之間的所有數(shù)

產(chǎn)生的序列應(yīng)該看起來是隨機的

這個函數(shù)應(yīng)該用32bit 算術(shù)高效實現(xiàn)

實現(xiàn)

#include   
#include   
static unsigned long rand_seed;  
void mysrand (unsigned long int);  
void myrand ();  
int  
main (void)  
{  
    int i;  
  
    mysrand (time (NULL));  
    for (i = 0; i < 100; i++)  
      {  
          myrand ();  
      }  
    return 0;  
}  
  
void  
mysrand (unsigned long seed)  
{  
    rand_seed = seed;  
}  
  
void  
myrand ()  
{  
    rand_seed = (rand_seed * 16807L) % ((1 << 31) - 1);  
    printf ("%ld ", rand_seed);  
}  

可以看到,這個實現(xiàn)和上面提到的 linux 的實現(xiàn)很像,其實就是一樣的。

& 隨機數(shù)使用

因為最近用的c++和python特別的多(我覺得這兩個語言是程序員們最需要掌握的兩種語言,別的都是補充 ~:)),所以下面我就只講這兩種語言的實現(xiàn)方式。

c++

實例程序

#include "stdafx.h"
#include 
#include 
int _tmain(int argc, _TCHAR* argv[])
{
 // 初始化隨機數(shù)種子
 // time函數(shù)返回從1970年1月1日零時零分零秒到目前為止所經(jīng)過的時間,單位為秒
 srand((int)time(NULL));
 int j;
 for (int i = 0; i < 10; i++) {
  j = (rand() * 10) / RAND_MAX + 1; // 生成1~10之間的隨機數(shù)
  printf("j = %d 
", j);
 }
 unsigned start = (rand() * 1000)/ RAND_MAX + 15550; // 生成15550~16549之間的隨機數(shù)
 printf("start = %d 
", start);
 start &= ~1; // 把start變?yōu)榕紨?shù),如果是奇數(shù),則start變?yōu)閟tart - 1的偶數(shù)
 printf("start = %d 
", start);
 getchar();
 return 0;
}

c++ 其實就是 srand 和 rand 兩個函數(shù)。
上面的都只是生成的整數(shù),如果需要浮點數(shù)什么的就需要自己再加以處理,而在python中提供了比較多的函數(shù)。

python

這塊的內(nèi)容是 Capricorn的實驗室的整理。其實這塊內(nèi)容直接去官網(wǎng)的doc翻譯就可以了,但是我有點懶,不太想去看了,就用了這篇博文的內(nèi)容~

random.random


random.random()用于生成一個0到1的隨機符點數(shù): 0 <= n < 1.0

random.uniform

random.uniform的函數(shù)原型為:random.uniform(a, b),用于生成一個指定范圍內(nèi)的隨機符點數(shù),兩個參數(shù)其中一個是上限,一個是下限。如果a>b,則生成的隨機數(shù)n: a <= n <= b。如果 $a

random.randint

random.randint()的函數(shù)原型為:random.randint(a, b),用于生成一個指定范圍內(nèi)的整數(shù)。其中參數(shù)a是下限,參數(shù)b是上限,生成的隨機數(shù)n: a <= n <= b。

random.randrange

random.randrange 的函數(shù)原型為:random.randrange([start], stop[, step]),從指定范圍內(nèi),按指定基數(shù)遞增的集合中 獲取一個隨機數(shù)。如:random.randrange(10, 100, 2),結(jié)果相當(dāng)于從[10, 12, 14, 16, ... 96, 98]序列中獲取一個隨機數(shù)。random.randrange(10, 100, 2)在結(jié)果上與 random.choice(range(10, 100, 2) 等效。

random.choice

random.choice從序列中獲取一個隨機元素。其函數(shù)原型為:random.choice(sequence)。參數(shù)sequence表示一個有序類型。這里要說明 一下:sequence在python不是一種特定的類型,而是泛指一系列的類型。list, tuple, 字符串都屬于sequence。有關(guān)sequence可以查看python手冊數(shù)據(jù)模型這一章。下面是使用choice的一些例子:

print random.choice("學(xué)習(xí)Python")   
print random.choice(["JGood", "is", "a", "handsome", "boy"])  
print random.choice(("Tuple", "List", "Dict"))  

random.shuffle

random.shuffle的函數(shù)原型為:random.shuffle(x[, random]),用于將一個列表中的元素打亂

random.sample

random.sample的函數(shù)原型為:random.sample(sequence, k),從指定序列中隨機獲取指定長度的片斷。sample函數(shù)不會修改原有序列。

OK,告一段落了~,朋友們,有沒有覺得進步了一點點呢~

paper done 2017/05/13

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/40631.html

相關(guān)文章

  • 重磅 | 完備的 AI 學(xué)習(xí)路線,最詳細的資源整理!

    摘要:是你學(xué)習(xí)從入門到專家必備的學(xué)習(xí)路線和優(yōu)質(zhì)學(xué)習(xí)資源。的數(shù)學(xué)基礎(chǔ)最主要是高等數(shù)學(xué)線性代數(shù)概率論與數(shù)理統(tǒng)計三門課程,這三門課程是本科必修的。其作為機器學(xué)習(xí)的入門和進階資料非常適合。書籍介紹深度學(xué)習(xí)通常又被稱為花書,深度學(xué)習(xí)領(lǐng)域最經(jīng)典的暢銷書。 showImg(https://segmentfault.com/img/remote/1460000019011569); 【導(dǎo)讀】本文由知名開源平...

    荊兆峰 評論0 收藏0
  • python進階筆記【2】 --- 一個奇怪的 __future__ 庫

    摘要:正文總所周知,和根本就是兩個東西,每次因為這個兼容性的問題都會把自己搞瘋。提供了模塊,把下一個新版本的特性導(dǎo)入到當(dāng)前版本,于是我們就可以在當(dāng)前版本中測試一些新版本的特性。傳送門不多,才個。 寫在前面 我是在學(xué)習(xí)cs231n的assignment3的課程,發(fā)現(xiàn)里面的代碼大量頻繁出現(xiàn)了這個庫,那我就很奇怪了,為什么有個future這個奇怪名字的庫會出現(xiàn)呢?到底這個庫又有什么用?下面就讓我為...

    Achilles 評論0 收藏0
  • Python

    摘要:最近看前端都展開了幾場而我大知乎最熱語言還沒有相關(guān)。有關(guān)書籍的介紹,大部分截取自是官方介紹。但從開始,標(biāo)準(zhǔn)庫為我們提供了模塊,它提供了和兩個類,實現(xiàn)了對和的進一步抽象,對編寫線程池進程池提供了直接的支持。 《流暢的python》閱讀筆記 《流暢的python》是一本適合python進階的書, 里面介紹的基本都是高級的python用法. 對于初學(xué)python的人來說, 基礎(chǔ)大概也就夠用了...

    dailybird 評論0 收藏0
  • 什么是 Python 編程語言?

    摘要:由設(shè)計,作為編程語言的繼承者,于年首次發(fā)布。表達式表達式是編程語言中的語法實體,可以對其進行評估以確定其值。它是編程語言解釋和計算以產(chǎn)生值的常量變量函數(shù)和運算符的組合。它在年年年和年被評為年度編程語言,是唯一四次獲得該獎項的語言。 ...

    1treeS 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<