一個有關PHP隨機數的坑…

來源:互聯網
上載者:User

php中擷取隨機數的方法很簡單,使用rand函數就可以了

 

int rand ( int $min , int $max )

一句調用就可以獲得指定範圍的隨機數。但是大家都知道,電腦中使用的隨機數實際是
偽隨機數,一般來說,為了增加隨機性,我們還會習慣在調用之前設定一下隨機種子:

 

 

void srand ([ int $seed ] )

按照其他語言的習俗,會在
srand的參數裡傳遞一個時間值,一般會傳遞目前時間的毫秒值或者微秒值進去。雖然從PHP4.2開始,調用rand的時候會自動調用srand,所以srand調用是一個並非必須的操作。

 

PHP中可以使用microtime()函數來擷取隨機數。於是,在一個一般性隨機數需求情境下,我們就可以使用下述代碼擷取隨機數了

 

<?php    srand(microtime());    echo rand(1, 25).PHP_EOL;    echo rand(1, 25).PHP_EOL;?>

執行代碼,我們得到了兩個隨機數。看似不錯,但是再次執行,卻發現得到的隨機數和上次的一模一樣。

這是啥狀況?我們明明已經設定srand種子為目前時間的毫秒值了。

查閱文檔,才發現其中的問題,原來在不帶參數的情況下,mircotime函數會以"msec sec" 的格式返回一個空格分隔的字串,經過自動類型轉換,srand實際得到的參數值是0,在固定隨機種子的情況下,會得到固定的隨機序列,因此每次執行指令碼都會得到相同的隨機數。

從PHP5開始,microtime增加了一個$get_as_float參數,通過傳遞true,可以讓microtime返回一個當前毫秒的float值,由於傳回值小數點之前是當前的秒值,因此對結果再乘以1000把小數點擴充到毫秒層級,這樣就可以安全的擷取隨機數了:

 

<?php    srand(microtime(true) * 1000);    echo rand(1, 25).PHP_EOL;    echo rand(1, 25).PHP_EOL;?>

 

連續訪問兩次,得到了不同的隨機數,再寫一個bash指令碼:

 

for i in $(seq 1 1 100)do    curl http://127.0.0.1/rnd.php    echo done

連續跑100次,測試通過。

 

其實。。。

前例中的代碼會報告一個

 

PHP Notice: A non well formed numeric value encountered

 

警告。但是如果指令碼是跑在服務或者後台進程中,則可能不容易發現問題。

或者。。。

PHP中已經有了一個mt_rand()的函數用來替換古老的rand,可以自動播種並且效率比rand高四倍。。。好吧,看來研究舊有問題和學習新鮮知識一個都不能少。。。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.