產品經理 : 老司機,你那邊開發個領取紅包的版塊。我給必定的金額總數,紅包個數,最高發放金額,以及最低發放金額,你要隨機生成固定個數的紅包,紅包總額不能超過金額總數。
老司機 : 你(筆者),去實現這個算法,把生成的紅包所有丟到數據庫裏面。php
好吧,就這樣,這個需求就讓我實現了。其實業務看起來講的很複雜,其實就是例如我有1000元,我想發放100個紅包,最高不能超過20塊,最低不能低於1塊。
當時我也不太清楚這個算法要怎麼寫,上網搜索了下,找到一種比較合理的算法,是用微積分去實現(我會把代碼貼出來)的。算法原理以下golang
(原文地址:http://blog.csdn.net/cleverco...)
我剛開始以爲這個算法確實很不錯,但仔細看了下里面的源碼後以爲會比較耗性能,並且回頭一看公司的需求,其實也就個紅包生成(在項目經理沒要求須要正態分佈的狀況下),不必把複雜簡單的東西弄複雜了。因此我思來想去想了一個晚上,終於寫出了個比較合理的算法。算法
/* * 獲取隨機紅包 * min<k<max * min(n-1) <= money - k <= (n-1)max * k <= money-(n-1)min * k >= money-(n-1)max */ function getRedPackage($money, $num, $min, $max) { $data = array(); if ($min * $num > $money) { return array(); } if($max*$num < $money){ return array(); } while ($num >= 1) { $num--; $kmix = max($min, $money - $num * $max); $kmax = min($max, $money - $num * $min); $kAvg = $money / ($num + 1); //獲取最大值和最小值的距離之間的最小值 $kDis = min($kAvg - $kmix, $kmax - $kAvg); //獲取0到1之間的隨機數與距離最小值相乘得出浮動區間,這使得浮動區間不會超出範圍 $r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2; $k = round($kAvg + $r); $money -= $k; $data[] = $k; } return $data; }
這個算法的原理其實就是根據剩餘不斷變化的平均值去加減隨機數作到不超過總額,但紅包的分佈就沒那麼平均。數據庫
差很少有三個月沒寫文章了,主要是這三個月一直在學習新的東西,相關php的工具,workman,kafka,以及golang。學的東西很雜,但也作出了效果,天天都在公司躲到11點後纔回家。筆者也建議phper新人們,不要單純限制在php語言裏面,以及去討論php是不是最好的編程語言之類的。畢竟能解決問題的武器就是好武器,一個工程師被公司聘請來就是解決問題的(大聲喊出來,咱們不是碼農)。編程