当前位置:首页 > PHP

php实现抽奖 概率

2026-02-16 13:35:05PHP

PHP实现抽奖概率的方法

方法一:使用数组和随机数

创建一个包含奖项和对应概率的数组,使用随机数进行抽奖判断。

php实现抽奖 概率

$prizes = [
    ['name' => '一等奖', 'probability' => 0.01],
    ['name' => '二等奖', 'probability' => 0.05],
    ['name' => '三等奖', 'probability' => 0.1],
    ['name' => '谢谢参与', 'probability' => 0.84]
];

function drawLottery($prizes) {
    $rand = mt_rand(1, 10000) / 10000;
    $currentProbability = 0;

    foreach ($prizes as $prize) {
        $currentProbability += $prize['probability'];
        if ($rand <= $currentProbability) {
            return $prize['name'];
        }
    }
    return end($prizes)['name'];
}

echo drawLottery($prizes);

方法二:使用权重分配

为每个奖项分配权重值,计算总权重后随机选择。

php实现抽奖 概率

$prizes = [
    ['name' => 'iPhone', 'weight' => 1],
    ['name' => 'iPad', 'weight' => 5],
    ['name' => '优惠券', 'weight' => 20],
    ['name' => '谢谢参与', 'weight' => 74]
];

function weightedDraw($prizes) {
    $totalWeight = array_sum(array_column($prizes, 'weight'));
    $rand = mt_rand(1, $totalWeight);
    $currentWeight = 0;

    foreach ($prizes as $prize) {
        $currentWeight += $prize['weight'];
        if ($rand <= $currentWeight) {
            return $prize['name'];
        }
    }
}

echo weightedDraw($prizes);

方法三:概率递减算法

适用于需要保证某些奖项必中或限制次数的场景。

$prizes = [
    ['name' => '特等奖', 'initial_prob' => 0.01, 'remaining' => 1],
    ['name' => '一等奖', 'initial_prob' => 0.05, 'remaining' => 5],
    ['name' => '二等奖', 'initial_prob' => 0.1, 'remaining' => 10],
    ['name' => '参与奖', 'initial_prob' => 1, 'remaining' => 1000]
];

function decreasingProbabilityDraw($prizes) {
    $totalRemaining = array_sum(array_column($prizes, 'remaining'));
    if ($totalRemaining <= 0) return '奖品已发完';

    $adjustedProbs = [];
    foreach ($prizes as $prize) {
        if ($prize['remaining'] > 0) {
            $adjustedProbs[] = [
                'name' => $prize['name'],
                'prob' => $prize['initial_prob'] * ($prize['remaining'] / $totalRemaining)
            ];
        }
    }

    $rand = mt_rand(1, 10000) / 10000;
    $currentProb = 0;

    foreach ($adjustedProbs as $prize) {
        $currentProb += $prize['prob'];
        if ($rand <= $currentProb) {
            return $prize['name'];
        }
    }

    return '谢谢参与';
}

echo decreasingProbabilityDraw($prizes);

方法四:使用概率别名算法

对于大量奖品的高效抽样方法,适合复杂概率分布场景。

class AliasMethod {
    private $n;
    private $prob;
    private $alias;

    public function __construct($weights) {
        $this->n = count($weights);
        $this->prob = array_fill(0, $this->n, 0);
        $this->alias = array_fill(0, $this->n, 0);

        $sum = array_sum($weights);
        $scaled = array_map(function($w) use ($sum) {
            return $w * $this->n / $sum;
        }, $weights);

        $small = [];
        $large = [];

        foreach ($scaled as $i => $w) {
            if ($w < 1) {
                $small[] = $i;
            } else {
                $large[] = $i;
            }
        }

        while (!empty($small) && !empty($large)) {
            $l = array_pop($small);
            $g = array_pop($large);

            $this->prob[$l] = $scaled[$l];
            $this->alias[$l] = $g;

            $scaled[$g] = ($scaled[$g] + $scaled[$l]) - 1;

            if ($scaled[$g] < 1) {
                $small[] = $g;
            } else {
                $large[] = $g;
            }
        }

        foreach ($large as $i) {
            $this->prob[$i] = 1;
        }

        foreach ($small as $i) {
            $this->prob[$i] = 1;
        }
    }

    public function draw() {
        $i = mt_rand(0, $this->n - 1);
        if (mt_rand() / mt_getrandmax() <= $this->prob[$i]) {
            return $i;
        } else {
            return $this->alias[$i];
        }
    }
}

$weights = [1, 2, 3, 4]; // 各奖项权重
$sampler = new AliasMethod($weights);
$result = $sampler->draw(); // 返回抽中的索引

注意事项

  • 随机数生成建议使用mt_rand()而非rand(),前者具有更好的随机性和性能
  • 浮点数比较时考虑精度问题,可使用整数运算避免
  • 高并发场景下需考虑原子操作或使用数据库事务
  • 实际应用中建议记录中奖日志,便于统计和审计

这些方法可根据实际需求组合使用,复杂抽奖系统可能需要结合数据库记录奖品库存和用户抽奖次数限制。

标签: 概率php
分享给朋友:

相关文章

php实现购物车

php实现购物车

PHP实现购物车功能 购物车功能是电商网站的核心模块之一,通常涉及商品添加、删除、数量修改和结算等操作。以下是使用PHP实现购物车功能的几种方法。 使用Session存储购物车数据 Session是…

php 实现自动收货

php 实现自动收货

PHP 实现自动收货功能 自动收货功能通常用于电商系统,在订单超过一定时间未手动确认收货时自动完成订单。以下是实现方法: 数据库设计 需要订单表包含以下关键字段: CREATE TABLE ord…

php实现异步

php实现异步

PHP 实现异步的方法 PHP 本身是同步执行的脚本语言,但可以通过以下方法模拟异步操作或实现异步效果: 使用多进程(pcntl_fork) 通过 pcntl_fork 创建子进程实现异步,适用于…

php 实现秒杀

php 实现秒杀

PHP 实现秒杀的关键技术 秒杀系统需要解决高并发、超卖、性能瓶颈等问题。以下是实现秒杀的核心方案: 使用 Redis 预减库存 将商品库存提前加载到 Redis 中,通过原子操作保证库存准确性:…

php 函数实现

php 函数实现

PHP 函数实现基础 PHP 函数的定义使用 function 关键字,后跟函数名和参数列表。函数名不区分大小写,但建议保持一致。 function functionName($param1, $p…

php 实现队列

php 实现队列

PHP 实现队列的方法 PHP 可以通过多种方式实现队列功能,以下是几种常见的实现方法: 使用数组实现队列 PHP 数组可以通过 array_push 和 array_shift 函数模拟队列的先进…