2024 年日本 PHP 研討會

random_int

(PHP 7, PHP 8)

random_int取得密碼學安全的、均勻選取的整數

說明

random_int(int $min, int $max): int

產生一個介於給定最小值和最大值之間均勻選取的整數。

此函式產生的隨機性適用於所有應用程式,包括產生長期使用的密鑰,例如加密金鑰。

隨機性來源的優先順序如下:

  • Linux:» getrandom()/dev/urandom

  • FreeBSD >= 12 (PHP >= 7.3):» getrandom()/dev/urandom

  • Windows (PHP >= 7.2):» CNG-API

    Windows:» CryptGenRandom

  • macOS (PHP >= 8.2; >= 8.1.9; >= 8.0.22 如果編譯時可以使用 CCRandomGenerateBytes):CCRandomGenerateBytes()

    macOS (PHP >= 8.1; >= 8.0.2):arc4random_buf(),/dev/urandom

  • NetBSD >= 7 (PHP >= 7.1; >= 7.0.1):arc4random_buf(),/dev/urandom

  • OpenBSD >= 5.5 (PHP >= 7.1; >= 7.0.1):arc4random_buf(),/dev/urandom

  • DragonflyBSD (PHP >= 8.1):» getrandom()/dev/urandom

  • Solaris (PHP >= 8.1):» getrandom()/dev/urandom

  • 任何前面未提及的作業系統和 PHP 版本組合:/dev/urandom
  • 如果沒有可用的來源或所有來源都無法產生隨機性,則會拋出 Random\RandomException

注意雖然此函式是在 PHP 7.0 中新增的,但 PHP 5.2 至 5.6(含)可以使用 » 使用者空間實作

參數

min

要返回的最小值。

max

要返回的最大值。

回傳值

從閉區間 [min, max] 中加密安全、均勻選擇的整數。minmax 都是可能的回傳值。

錯誤/例外

更新日誌

版本 說明
8.2.0 如果 CSPRNG 失敗,此函式現在會拋出 Random\RandomException。先前會拋出普通的 Exception

範例

範例 #1 random_int() 範例

<?php
var_dump
(random_int(100, 999));
var_dump(random_int(-1000, 0));
?>

上述範例將輸出類似以下的內容:

int(248)
int(-898)

另請參閱

新增筆記

使用者貢獻的筆記 4 則筆記

s rotondo90 at gmail com
8 年前
這是一個簡單的向下相容函式,適用於 PHP >= 5.1

<?php
if (!function_exists('random_int')) {
function
random_int($min, $max) {
if (!
function_exists('mcrypt_create_iv')) {
trigger_error(
'必須載入 mcrypt 才能使 random_int 運作',
E_USER_WARNING
);
return
null;
}

if (!
is_int($min) || !is_int($max)) {
trigger_error('$min 與 $max 必須是整數值', E_USER_NOTICE);
$min = (int)$min;
$max = (int)$max;
}

if (
$min > $max) {
trigger_error('$max 不能小於 $min', E_USER_WARNING);
return
null;
}

$range = $counter = $max - $min;
$bits = 1;

while (
$counter >>= 1) {
++
$bits;
}

$bytes = (int)max(ceil($bits/8), 1);
$bitmask = pow(2, $bits) - 1;

if (
$bitmask >= PHP_INT_MAX) {
$bitmask = PHP_INT_MAX;
}

do {
$result = hexdec(
bin2hex(
mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
)
) &
$bitmask;
} while (
$result > $range);

return
$result + $min;
}
}
?>

隨機性測試

<?php
$max
= 100; // 隨機值的數量
$test = 1000000;

$array = array_fill(0, $max, 0);

for (
$i = 0; $i < $test; ++$i) {
++
$array[random_int(0, $max-1)];
}

function
arrayFormatResult(&$item) {
global
$test, $max; // 盡量避免在現今程式碼中使用全局變數 ;)

$perc = ($item/($test/$max))-1;
$item .= ' '. number_format($perc, 4, '.', '') .'%';
}

array_walk($array, 'arrayFormatResult');

print_r($array);
?>
bens at effortlessis dot com
4 年前
在我的系統上 (第五代 i7) random_int() 執行相同次數計算所需的時間比 rand() 大約長 14 倍。

for ($i=0; $i<10000000; $i++)
$x = rand(1, PHP_INT_MAX);

rand() 花費 0.86 秒,random_int() 花費 12.29 秒。所以要盡量少用 random_int()。

如果不需要真正的隨機性,特別是在緊密的迴圈中,請使用 rand()。
ccb_bc at hotmail dot com
5 年前
<?php
// PHP >= 7
function str_rand(int $length = 16){
$x = '';
for(
$i = 1; $i <= $length; $i++){
$x .= dechex(random_int(0,255));
}
return
substr($x, 0, $length);
}
var_dump(str_rand());
?>
Hayley Watson
1 年前
一個用於產生版本 4 GUID 的小型函式。

<?php
function v4uuid()
{
$a = str_pad(dechex(random_int(0x0000_0000, 0xffff_ffff)), '0', STR_PAD_LEFT);
$b = str_pad(dechex(random_int(0x0000, 0xffff)), '0', STR_PAD_LEFT);
$c = dechex(random_int(0x4000, 0x4fff));
$d = dechex(random_int(0x8000, 0xbfff));
$e = str_pad(dechex(random_int(0x0000_0000_0000, 0xffff_ffff_ffff)), '0', STR_PAD_LEFT);
return
"$a-$b-$c-$d-$e";
}
?>
To Top