iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
Modern Web

工作後才知道的後端 30 件小事系列 第 13

PHP 亂數產生介於 0 到 1 之間的浮點數

  • 分享至 

  • xImage
  •  

前言

有一次在串接合作廠商的 API 時,需要把他原本取 token 的 javascript 改寫成 PHP 版;其中有一個步驟需要用 PHP 產生介於 0 到 1 之間的浮點數,看似簡單卻卡了我一陣子。

原因是 PHP 似乎沒有提供一個函式可以直接做到(有的話請告訴我>_<)

rand()

PHP 提供的亂數函式,會回傳一個整數,可以給訂一個範圍

rand(0,15); // 0 <= output <= 15

如果為給定範圍,會回傳一個 0 到 RAND_MAX 的隨機整數。
而 RAND_MAX 是多少呢?這會根據所使用系統而有所不同,可以透過 getrandmax() 得知。

getrandmax(); // output 2147483647,2的31次方減1,32位元有號整數的最大值

有號整數

0 ~ 1 之間的亂數

實作前要再確認是需求是哪種

  • 0 < output < 1
  • 0 <= output <= 1

可以用rand()除以最大值 RAND_MAX。

rand() / getrandmax(); // 0 <= output <= 1

但這做法理論上會包含 0 和 1,只是機率很小,保守一點可以做排除。

$rand = rand() / getrandmax();
while ($rand == 1 || $rand == 0) {
    $rand = rand() / getrandmax();
}

另外分享一個另類的做法,就是用 sin() ,利用他會回傳一個 -1 到 1 浮點數的特性來做,以前做動畫常常會用到(茶)
感謝幫友提醒,這方法數值偏兩端(0 跟 1)的機率會比中間(0.5)的高

// 確實會產生介於 0 到 1 之間的數,但非平均分佈
(sin(rand())+1)/2;

注意,這邊 sin() 的輸入單位是弧度 (角度轉弧度)


上一篇
PHP Switch 細節:Loose Comparison
下一篇
Laravel ChunkById
系列文
工作後才知道的後端 30 件小事20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
淺水員
iT邦大師 6 級 ‧ 2021-09-13 13:00:06
//0 <= output < 1
rand() / (getrandmax() + 1);

//0 < output < 1
(rand() + 1) / (getrandmax() + 2);

另外用 sin 函數跑出來應該會不均勻吧?
(sin(rand())+1)/2 數值偏兩端( 0跟 1)的機率會比中間(0.5)的高

阿對...會不平均...
感謝提醒!已補充在正文

我要留言

立即登入留言