当前位置:首页 > 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实现图片上传

实现图片上传的基本步骤 创建HTML表单用于文件上传,表单需设置enctype="multipart/form-data"属性,确保文件数据正确传输。 <form action="uploa…

php实现websocket

php实现websocket

PHP 实现 WebSocket WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。PHP 可以通过多种方式实现 WebSocket 功能,以下是几种常见的方法: 使用 Rat…

php实现表单

php实现表单

PHP 表单基础实现 创建一个简单的 PHP 表单需要 HTML 表单结构和 PHP 处理脚本。以下是一个完整的示例: HTML 表单部分 (form.html) <form action=…

php实现异步

php实现异步

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

php实现的分页

php实现的分页

PHP 实现分页的方法 基本分页逻辑 分页的核心在于计算总页数、当前页码以及数据偏移量。假设每页显示 10 条数据: $current_page = isset($_GET['page']) ? (…

php 实现类

php 实现类

PHP 类的基本实现 在 PHP 中,类通过 class 关键字定义,后跟类名和一对花括号。类名通常遵循大驼峰命名法(如 ClassName)。以下是基本语法: class ClassName {…