>백엔드 개발 >PHP 튜토리얼 >PHP 빨간 봉투 알고리즘 구현에 대한 아이디어 공유(개발 코드 첨부)

PHP 빨간 봉투 알고리즘 구현에 대한 아이디어 공유(개발 코드 첨부)

藏色散人
藏色散人앞으로
2021-09-03 15:50:593852검색
根据很多需求的使用场景,如发红包、砍价类需求,这两个功能都有一个同样的特点,如下:

빨간 봉투

1. 총 금액
2. 빨간 봉투의 개수
3. 빨간 봉투의 최소 수량

총 할인 금액2. . 필요한 인원수 완전 교섭(인원은 수요에 따라 다름)


고정된 교섭 인원

    교섭할 인원 무작위
  • 교섭할 인원 무작위 지정
  • 포인트 2: 3명 규칙은 모두 규칙에 따라 여러 사람에게 도달해야 합니다

  • 3. 최소 협상 금액

개발 아이디어

검증 매개 변수

최소 금액은 0보다 작을 수 없습니다

총 금액은 수량에 최소금액을 곱한 금액을 초과할 수 없습니다

배분금액
평균금액을 구합니다(총액/잔여수량)

배포금액 평균금액은 이하이고 최소량은 직접 할당됩니다. 진폭 비율을 가져옵니다. 최소값은 -1보다 작을 수 없으며 최대값은 1

진폭 계산(평균 * (1+진폭 비율))

분배량 판단 분배량이 최소 금액 또는 배분 금액수취 가능한 최대 금액보다 큰 경우 ((최소 금액 + 남은 총액) - (남은 수량 × 최소 금액) ))) 재할당
금액이 마지막이면 남은 금액 모두 할당 小于等于最金额时直接分配最小金额
获取金额幅度比例 最小值不允许小于 -1 最大值不允许大于 1
得出分配金额  幅度计算(平均值*(1+幅度比例))
分配金额判断 分配金额小于最小金额或者分配金额大于 可领取最大金额
개발 코드

<?php

/**
 * 发送红包
 * Class sandRed
 */
class sandRed
{
    #红包金额
    protected $amount;
    #红包个数
    protected $num;
    #领取的红包最小金额
    protected $minAmount;
    #红包分配结果
    protected $amountArr = [];

    public function __construct($amount, $num = 1, $minAmount = 1)
    {
        $this->amount = $amount;
        $this->num = $num;
        $this->minAmount = $minAmount;
    }

    /**
     * 处理返回
     * @return array
     * @throws Exception
     */
    public function handle()
    {
        # 验证
        if ($this->amount < $validAmount = $this->minAmount * $this->num) {
            throw new Exception('红包总金额必须≥'.$validAmount.'元');
        }
        # 分配红包
        $this->allot();
        return $this->amountArr;
    }

    /**
     * 分配红包
     */
    protected function allot()
    {
        # 剩余可分配的红包个数
        $num = $this->num;

        # 剩余可领取的红包金额
        $amount = $this->amount;
        while ($num >= 1) {
            if ($num == 1) {
                # 剩余一个的时候,直接取剩余红包
                $coupon_amount = $this->formattingAmount($amount);
            } else {

                # 平均金额
                $avgAmount = $this->formattingAmount($amount / $num);

                # 分配金额
                $countAllotAmount = $this->countAllotAmount($avgAmount, $amount, $num);

                # 剩余的红包的平均金额
                $coupon_amount = $this->formattingAmount($countAllotAmount);
            }
            # 追加分配金额
            $this->amountArr[] = $coupon_amount;

            # 计算剩余金额
            $amount -= $coupon_amount;

            $num--;
        }
        # 随机打乱
        // shuffle($this->amountArr);
    }

    /**
     * 计算分配的红包金额
     * @param float $avgAmount 每次计算的平均金额
     * @param float $amount 剩余可领取金额
     * @param int $num 剩余可领取的红包个数
     * @return float
     */
    protected function countAllotAmount($avgAmount, $amount, $num)
    {
        # 如果平均金额小于等于最低金额,则直接返回最低金额
        if ($avgAmount <= $this->minAmount) {
            return $this->minAmount;
        }
        # 浮动比率
        $floatingRate = $this->floatingRate();

        # 分配金额
        $allotAmount = $avgAmount * (1 + $floatingRate);

        # 浮动计算
        $coupon_amount = $this->formattingAmount($allotAmount);

        # 如果低于最低金额或超过可领取的最大金额,则重新获取
        if ($coupon_amount < $this->minAmount || $coupon_amount > $this->canReceiveMaxAmount($amount, $num)) {
            return $this->countAllotAmount($avgAmount, $amount, $num);
        }
        return $coupon_amount;
    }

    /**
     * 计算分配的红包金额-可领取的最大金额
     * @param $amount
     * @param $num
     * @return float|int
     */
    protected function canReceiveMaxAmount($amount, $num)
    {
        return $this->minAmount + $amount - $num * $this->minAmount;
    }

    /**
     * 红包金额浮动比例
     * @return float|int
     */
    protected function floatingRate()
    {
        # 60%机率获取剩余平均值的大幅度红包(可能正数、可能负数)
        if (rand(1, 100) <= 60) {
            # 上下幅度70%
            return rand(-70, 70) / 100;
        }
        # 其他情况,上下浮动30%;
        return rand(-30, 30) / 100;
    }

    /**
     * 格式化金额,保留2位
     * @param $amount
     * @return string
     */
    protected function formattingAmount($amount)
    {
        return sprintf(&#39;%01.2f&#39;, round($amount, 2));
    }
}

총 금액
  • $amount = 1;
할당 수량
  • $num = 10;
최소 금액
  • $minAmount = 0.01;
    
    $red = new sandRed($amount, $num, $minAmount);
    
    $res = $red->handle();
    print_r($res);
    출력 결과 [0.10,0, 04,0.08, 0.04,0.16.14,0.11,0.11,0.09]
    • echo array_sum($res);
    output 결과 1
    REMEDENDENCERONDER

위 내용은 PHP 빨간 봉투 알고리즘 구현에 대한 아이디어 공유(개발 코드 첨부)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제