iOS rand() random() arc4random()探究

首先我們先來看下頭各自所屬文件的聲明

uint32_t    arc4random(void);
int         rand(void) __swift_unavailable("Use arc4random instead.");
long        random(void) __swift_unavailable("Use arc4random instead.");

可以看出arc4random()random()、rand()函數(shù)返回類型分別為uint32_t,int,long,現(xiàn)在的iOS硬件設(shè)備幾乎都是64位,由于C語言生成的隨機(jī)數(shù)為無符號數(shù),即都是正的,我們可以得出隨機(jī)數(shù)取值范圍。

函數(shù)名 返回值 取值范圍
rand() int 0~2147483647
random() long 0~2147483647
arc4random() uint32_t 0~4294967295

#define RAND_MAX 0x7fffffff,RAND_MAX的值16進(jìn)制0x7ffffff轉(zhuǎn)換為10進(jìn)制為2147483647。
可以得出取值范圍arc4random() > (rand() = random())

下面我們來看一段代碼:

    for (int i = 0; i < 5; i ++) {
         NSLog(@"%@ - %@ - %@",@(random()),@(random()),@(arc4random()));
    }

我們連續(xù)運(yùn)行幾次得到結(jié)果如下:

     第一次:
     1804289383 - 846930886 - 1208611301
     1681692777 - 1714636915 - 3355735759
     1957747793 - 424238335 - 2781113645
     719885386 - 1649760492 - 1801593043
     596516649 - 1189641421 - 460884511
     
     第二次:
     1804289383 - 846930886 - 1119699280
     1681692777 - 1714636915 - 3441628103
     1957747793 - 424238335 - 3443635443
     719885386 - 1649760492 - 3847802969
     596516649 - 1189641421 - 3735080216
     
     第三次:
     1804289383 - 846930886 - 196821635
     1681692777 - 1714636915 - 406729781
     1957747793 - 424238335 - 1463174244
     719885386 - 1649760492 - 2704772030
     596516649 - 1189641421 - 3925712717
     
     ···

我們可以發(fā)現(xiàn),每次rand()random()每次輸出結(jié)果都是一樣的,而arc4random()輸出結(jié)果則是隨機(jī)的。
為什么會(huì)出現(xiàn)這種結(jié)果呢?
回答這個(gè)問題前我們先了解幾個(gè)概念。

  • 隨機(jī)數(shù)和偽隨機(jī)數(shù)

真正意義上的隨機(jī)數(shù)(或者隨機(jī)事件)在某次產(chǎn)生過程中是按照實(shí)驗(yàn)過程中表現(xiàn)的分布概率隨機(jī)產(chǎn)生的,其結(jié)果是不可預(yù)測的,是不可見的。

而計(jì)算機(jī)中的隨機(jī)數(shù)并不是真正的隨機(jī)數(shù),而是通過通過隨機(jī)函數(shù)按照一定算法模擬產(chǎn)生的,其結(jié)果是確定可預(yù)見的,所以用計(jì)算機(jī)隨機(jī)函數(shù)所產(chǎn)生的“隨機(jī)數(shù)”并不隨機(jī),是偽隨機(jī)數(shù)。

硬件方法是指采集某一種物理噪聲,經(jīng)過抽樣、量化之后得到的隨機(jī)數(shù)。例如大氣噪聲。此類噪聲是由自然界中的布朗運(yùn)動(dòng)等現(xiàn)象產(chǎn)生的,因此可以看作真正的隨機(jī)數(shù)生成器,只要是通過算法產(chǎn)生的隨機(jī)數(shù)都是偽隨機(jī)數(shù)。通過真實(shí)隨機(jī)事件取得的隨機(jī)數(shù)才是真隨機(jī)數(shù)。

  • 隨機(jī)種子(Random Seed)

一種以隨機(jī)數(shù)作為對象的以真隨機(jī)數(shù)(種子)為初始條件的隨機(jī)數(shù)。計(jì)算機(jī)中的隨機(jī)數(shù)都是偽隨機(jī)數(shù),以一個(gè)真隨機(jī)數(shù)(種子)作為初始條件,然后用一定的算法不停迭代產(chǎn)生隨機(jī)數(shù)。通俗來講種子就是個(gè)序號,這個(gè)序號交給一個(gè)數(shù)列管理器,通過這個(gè)序號,你從管理器中取出一個(gè)數(shù)列,這個(gè)數(shù)列就是你通過那個(gè)序號得到的隨機(jī)數(shù)。

理解了這兩個(gè)概念我們可以知道:

如果你種子相同,你生成的數(shù)列肯定是每次一樣的,種子不同,不過讓你看起來覺得每次生成的數(shù)列不一樣罷了。

種子和隨機(jī)數(shù)列是一一對應(yīng)的。{An}=f(x), x 就是種子,F(xiàn)()是算法,{An}是數(shù)列,這個(gè)數(shù)列看上去是隨機(jī)的,這是因?yàn)锳n的通項(xiàng)很復(fù)雜。

種子的選擇有規(guī)律嗎?肯定是有!那么生成的隨機(jī)數(shù)也一定是有規(guī)律的了。既然有規(guī)律,那肯定就是偽隨機(jī)了,因?yàn)槟悴恢婪N子和隨機(jī)數(shù)算法對你來說當(dāng)然就是隨機(jī)數(shù)。

現(xiàn)在我們可以解釋前面那段代碼 rand()random()每次輸出結(jié)果都是一樣的,而arc4random()輸出結(jié)果則是隨機(jī)的這個(gè)問題了。

產(chǎn)生偽隨機(jī)數(shù)需要隨機(jī)種子和隨機(jī)算法。rand()random()每次產(chǎn)生的值都是一樣的,那說明它們的隨機(jī)種子每次是一樣,下面我們給rand()random()一個(gè)隨機(jī)的隨機(jī)種子看下會(huì)有怎樣結(jié)果:

    //加入隨機(jī)種子
    srandom((unsigned int)time(0));
    //產(chǎn)生隨機(jī)數(shù)
    for (int i = 0; i < 5; i ++) {
        NSLog(@"%@",@(random()%100));
    }
    /*輸出 
    第一次8 22 90 91 20 
    第一次93 84 34 50 50 
    第一次13 33 22 45 78 
    */

其中把rand()函數(shù)換成random()每次輸出結(jié)果也都不同,即得到的偽隨機(jī)數(shù)不同。
arc4random()無論加不加隨機(jī)種子,每次輸出的偽隨機(jī)數(shù)都不同。
我嘗試每次把程序卸載重裝,每次產(chǎn)生的隨機(jī)數(shù)也不一樣。
通過以上我們得出結(jié)論:
對于 rand()random()隨機(jī)函數(shù),每次安裝程序的時(shí)候系統(tǒng)會(huì)為其設(shè)置一個(gè)固定的隨機(jī)種子,如果不主動(dòng)設(shè)置隨機(jī)種子,每次得到的隨機(jī)數(shù)都將一樣??梢酝ㄟ^srandom((unsigned int)time(0));為其設(shè)置隨機(jī)種子,隨機(jī)種子不同,每次隨機(jī)函數(shù)得到的結(jié)果不同。
對于arc4random(),使用時(shí)候不需要生成隨機(jī)種子,系統(tǒng)已經(jīng)默認(rèn)為其生成了隨機(jī)種子。

通過上面比較,arc4random()不僅取值范圍大而且不需要主動(dòng)設(shè)置隨機(jī)種子,是我們比較理想的計(jì)算隨機(jī)數(shù)的選擇。通過蘋果api

int     rand(void) __swift_unavailable("Use arc4random instead.");
long    random(void) __swift_unavailable("Use arc4random instead.");

也能看出我們使用arc4random()更為妥當(dāng)。

以上就是本文全部內(nèi)容,如果不當(dāng)之處,還望指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容