闲来无事,PHP撸两个红包算法

早上地铁里无聊,看到CSDN公众号推的一篇文章,是随机红包的实现,有兴趣的可以看原文,这里只做php版的代码实现


漫画:如何实现抢红包算法?

https://mp.weixin.qq.com/s/7yDbdKHJ3OmNw_015Jc8Cg

废话不多说,上代码:


class RedPackageService{
    private static $instance;
    private function __construct()
    {
    }
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }
    public static function getInstance()
    {
        if(!(self::$instance instanceof  self))
            self::$instance = new self;
        return self::$instance;
    }

    /**保证每个人拿到的概率相同(保证公平)
     * @param $total int 红包总金额,单位分
     * @param $number int 参与抢红包的数量
     * @return array
     * Array
        (
            [0] => 22.05 单位元,精确到分
            [1] => 9.15
            [2] => 27.35
            [3] => 12.84
            [4] => 25.74
            [5] => 0.94
            [6] => 26.93
        )
     */
    public function byAverage($total,$number)
    {
        $data = [];

        for($i=0;$i<$number;$i++)
        {
            if($number ==  ($i+1))
                $data[] = round($total/100,2);
            else {
                $area = round($total / ($number - $i), 0) * 2;
                $re = random_int(1, $area);
                $data[] = round($re/100,2);
                $total -= $re;
            }
        }
        return $data;
    }


    /**保证红包金额随机性
     * @param $total int 红包总金额 单位分
     * @param $number int 参与人数
     * @return array
     * Array
        (
            [0] => 3.49
            [1] => 7.83
            [2] => 27.24
            [3] => 4.53
            [4] => 15.31
            [5] => 32.61
            [6] => 33.99
        )
     */
    public function byRandom($total,$number)
    {
        $data = $divided_points = [];

        //获取随机分割点,在0-$total之间寻找$number-1个
        for($i=0;$i<$number-1;$i++)
        {
            $tmp_point = random_int(1,$total-1);
            //检查分割点是否存在
            while (in_array($tmp_point,$divided_points))
            {
                $tmp_point = random_int(1,$total-1);
            }
            array_push($divided_points,$tmp_point);

        }
        //加入终止分割点
        array_push($divided_points,$total);
        //分割点排序,从小到大,index会变动
        asort($divided_points);
        //根据分割点获取随机金额
        $a = 0;
        foreach ($divided_points as $b)
        {
            $data[] = round(($b-$a)/100,2);
            $a = $b;
        }
//        for($i=1;$i<$number;$i++)
//            $data[] = round(($divided_points[$i]-$divided_points[$i-1])/100,2);

        return $data;

    }
}

测试执行代码

        $re = RedPackageService::getInstance()->byRandom(12500,7);
        print_r($re);
可能需要注意一下你的namespace

两个方法各有所长各有缩短,大家理性看待,随便玩玩,开心就好

猜你喜欢

转载自blog.csdn.net/liangxun0712/article/details/80075282