


Algorithme PHP pour générer des enveloppes rouges aléatoires
Idée de base
En termes de génération de nombres aléatoires, j'ai appris de ce blogueur @Le misérable oncle Idée :
Texte original : Par exemple, si vous souhaitez distribuer 1 enveloppe rouge à N personnes, cela équivaut en fait à obtenir N données en pourcentage. La condition est que la somme de ces N pourcentages = 100/. 100. La moyenne de ces N pourcentages est de 1/N. Et ces N pourcentages de données sont conformes à une distribution normale (la plupart des valeurs sont relativement proches de la moyenne).
Interprétation : Par exemple, si j'ai 1 000 yuans et que j'envoie 50 enveloppes rouges, je choisirai au hasard 50 nombres, puis calculerai la moyenne moyenne de ces 50 nombres, en utilisant avg/(1/N) , et vous obtiendrez un mixrand de nombre de base, puis diviserez les 50 nombres générés aléatoirement par le mixrand pour obtenir le pourcentage de randVal de chaque nombre par rapport à la base, puis multiplierez randVal par 1 000 yuans pour obtenir le montant spécifique de chaque enveloppe rouge. .
Implémentation de l'algorithme
Parler ne coûte pas cher, montre-moi ton code !
Algorithme de génération de base :
<?php /* * Note: 红包生成随机算法 */ class Reward { public $rewardMoney; // 红包金额、单位元 public $rewardNum; // 红包数量 // 执行红包生成算法 public function splitReward($rewardMoney, $rewardNum, $max, $min) { // 传入红包金额和数量,因为小数在计算过程中会出现很大误差,所以我们直接把金额放大100倍,后面的计算全部用整数进行 $min = $min * 100; $max = $max * 100; // 预留出一部分钱作为误差补偿,保证每个红包至少有一个最小值 $this->rewardMoney = $rewardMoney * 100 - $rewardNum * $min; $this->rewardNum = $rewardNum; // 计算出发出红包的平均概率值、精确到小数4位。 $avgRand = 1 / $this->rewardNum; $randArr = []; // 定义生成的数据总合sum $sum = 0; $t_count = 0; while ($t_count < $rewardNum) { // 随机产出四个区间的额度 $c = rand(1, 100); if ($c < 15) { $t = round(sqrt(mt_rand(1, 1500))); } else if ($c < 65) { $t = round(sqrt(mt_rand(1500, 6500))); } else if ($c < 95) { $t = round(sqrt(mt_rand(6500, 9500))); } else { $t = round(sqrt(mt_rand(9500, 10000))); } ++$t_count; $sum += $t; $randArr[] = $t; } // 计算当前生成的随机数的平均值,保留4位小数 $randAll = round($sum / $rewardNum, 4); // 为将生成的随机数的平均值变成我们要的1/N,计算一下每个随机数要除以的总基数mixrand。此处可以约等处理,产生的误差后边会找齐 // 总基数 = 均值/平均概率 $mixrand = round($randAll / $avgRand, 4); // 对每一个随机数进行处理,并乘以总金额数来得出这个红包的金额。 $rewardArr = array(); foreach ($randArr as $key => $randVal) { // 单个红包所占比例randVal $randVal = round($randVal / $mixrand, 4); // 算出单个红包金额 $single = floor($this->rewardMoney * $randVal); // 小于最小值直接给最小值 if ($single < $min) { $single += $min; } // 大于最大值直接给最大值 if ($single > $max) { $single = $max; } // 将红包放入结果数组 $rewardArr[] = $single; } // 对比红包总数的差异、将差值放在第一个红包上 $rewardAll = array_sum($rewardArr); // 此处应使用真正的总金额rewardMoney,$rewardArr[0]可能小于0 $rewardArr[0] = $rewardMoney * 100 - ($rewardAll - $rewardArr[0]); // 第一个红包小于0时,做修正 if ($rewardArr[0] < 0) { rsort($rewardArr); $this->add($rewardArr, $min); } rsort($rewardArr); // 随机生成的最大值大于指定最大值 if ($rewardArr[0] > $max) { // 差额 $diff = 0; foreach ($rewardArr as $k => &$v) { if ($v > $max) { $diff += $v - $max; $v = $max; } else { break; } } $transfer = round($diff / ($this->rewardNum - $k + 1)); $this->diff($diff, $rewardArr, $max, $min, $transfer, $k); } return $rewardArr; } // 处理所有超过最大值的红包 public function diff($diff, &$rewardArr, $max, $min, $transfer, $k) { // 将多余的钱均摊给小于最大值的红包 for ($i = $k; $i < $this->rewardNum; $i++) { // 造随机值 if ($transfer > $min * 20) { $aa = rand($min, $min * 20); if ($i % 2) { $transfer += $aa; } else { $transfer -= $aa; } } if ($rewardArr[$i] + $transfer > $max) continue; if ($diff - $transfer < 0) { $rewardArr[$i] += $diff; $diff = 0; break; } $rewardArr[$i] += $transfer; $diff -= $transfer; } if ($diff > 0) { $i++; $this->diff($diff, $rewardArr, $max, $min, $transfer, $k); } } // 第一个红包小于0,从大红包上往下减 public function add(&$rewardArr, $min) { foreach ($rewardArr as &$re) { $dev = floor($re / $min); if ($dev > 2) { $transfer = $min * floor($dev / 2); $re -= $transfer; $rewardArr[$this->rewardNum - 1] += $transfer; } elseif ($dev == 2) { $re -= $min; $rewardArr[$this->rewardNum - 1] += $min; } else { break; } } if ($rewardArr[$this->rewardNum - 1] > $min || $rewardArr[$this->rewardNum - 1] == $min) { return; } else { $this->add($rewardArr, $min); } } }
Considérez les détails
Le code ci-dessous est utilisé pour contrôler une logique métier spécifique et mettre de côté des montants fixes maximum et minimum d'enveloppe rouge en fonction de besoins spécifiques lors de l'appel de splitReward(total ; ,num,max−0.01,min) dans le code pour générer des enveloppes rouges, la valeur maximale que j'ai transmise a été réduite de 0,01. Cela garantit que la valeur maximale de l'enveloppe rouge générée ne dépassera jamais la valeur maximale que nous avons définie.
<?php class CreateReward{ /* * 生成红包 * @param int $total 红包总金额 * @param int $num 红包总数量 * @param int $max 红包最大值 * */ public function random_red($total, $num, $max, $min) { // 总共要发的红包金额,留出一个最大值; $total = $total - $max; $reward = new Reward(); $result_merge = $reward->splitReward($total, $num, $max - 0.01, $min); sort($result_merge); $result_merge[1] = $result_merge[1] + $result_merge[0]; $result_merge[0] = $max * 100; foreach ($result_merge as &$v) { $v = floor($v) / 100; } return $result_merge; } }
Test d'instance
Code de base
Définissez d'abord diverses valeurs initiales.
<?php /** * Created by PhpStorm. * User: lufei * Date: 2017/1/4 * Time: 22:49 */ header('content-type:text/html;charset=utf-8'); ini_set('memory_limit', '128M'); require_once('CreateReward.php'); require_once('Reward.php'); $total = 50000; $num = 300000; $max = 50; $min = 0.01; $create_reward = new CreateReward();
Test de performance
En raison de la limitation de memory_limit, je n'ai mesuré la moyenne que 5 fois, et les résultats étaient tous autour de 1,6 s.
for ($i=0; $i<5; $i++) { $time_start = microtime_float(); $reward_arr = $create_reward->random_red($total, $num, $max, $min); $time_end = microtime_float(); $time[] = $time_end - $time_start; } echo array_sum($time)/5; function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); }
Résultats d'exécution :
Vérification des données
1) Si la valeur est fausse
Détecté oui Il n'y a pas de valeurs négatives, y a-t-il une valeur maximale, combien de valeurs maximales y a-t-il et y a-t-il une valeur inférieure à la valeur minimale.
$reward_arr = $create_reward->random_red($total, $num, $max, $min); sort($reward_arr);//正序,最小的在前面 $sum = 0; $min_count = 0; $max_count = 0; foreach($reward_arr as $i => $val) { if ($i<3) { echo "<br />第".($i+1)."个红包,金额为:".$val."<br />"; } if ($val == $max) { $max_count++; } if ($val < $min) { $min_count++; } $val = $val*100; $sum += $val; } //检测钱是否全部发完 echo '<hr>已生成红包总金额为:'.($sum/100).';总个数为:'.count($reward_arr).'<hr>'; //检测有没有小于0的值 echo "<br />最大值:".($val/100).',共有'.$max_count.'个最大值,共有'.$min_count.'个值比最小值小';
Résultats d'exploitation :
2) Distribution normale
Notez que lors du dessin, ne donnez pas trop d'enveloppes rouges sinon, le. la page ne peut pas être rendue et plantera.
$reward_arr = $create_reward->random_red($total, $num, $max, $min); $show = array(); rsort($reward_arr); // 为了更直观的显示正态分布效果,需要将数组重新排序 foreach($reward_arr as $k=>$value) { $t=$k%2; if(!$t) $show[]=$value;; else array_unshift($show,$value); } echo "设定最大值为:".$max.',最小值为:'.$min.'<hr />'; echo "<table style='font-size:12px;width:600px;border:1px solid #ccc;text-align:left;'><tr><td>红包金额</td><td>图示</td></tr>"; foreach($show as $val) { // 线条长度计算 $width=intval($num*$val*300/$total); echo "<tr><td> {$val} </td><td width='500px;text-align:left;'><hr style='width:{$width}px;height:3px;border:none;border-top:3px double red;margin:0 auto 0 0px;'></td></tr>"; } echo "</table>";
Résultats d'exécution :
.PS : Un ami m'a demandé si les données générées avaient été vérifiées mathématiquement pour se conformer à la distribution normale standard, car je ne suis pas bon en mathématiques. Je n'y ai pas vraiment pensé, je lui ressemblais et je pensais que c'était lui. Maintenant que j'ai rencontré ce problème, je dois le résoudre, j'ai donc utilisé la fonction intégrée de PHP pour le calculer. Le résultat calculé est encore relativement proche d'une distribution normale lorsque la quantité de données est petite, mais lorsque la quantité de données est faible. augmente, ça ne peut pas. Regardez, je ne comprends pas très bien cela. Si cela vous intéresse, vous pouvez en découvrir la raison.
Quatre fonctions de php : stats_standard_deviation (écart type), stats_variance (variance), stats_kurtosis (kurtosis), stats_skew (asymétrie). L'utilisation des fonctions ci-dessus nécessite l'installation de l'extension stats
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

PHP 8.4 apporte plusieurs nouvelles fonctionnalités, améliorations de sécurité et de performances avec une bonne quantité de dépréciations et de suppressions de fonctionnalités. Ce guide explique comment installer PHP 8.4 ou mettre à niveau vers PHP 8.4 sur Ubuntu, Debian ou leurs dérivés. Bien qu'il soit possible de compiler PHP à partir des sources, son installation à partir d'un référentiel APT comme expliqué ci-dessous est souvent plus rapide et plus sécurisée car ces référentiels fourniront les dernières corrections de bogues et mises à jour de sécurité à l'avenir.

CakePHP est un framework open source pour PHP. Il vise à faciliter grandement le développement, le déploiement et la maintenance d'applications. CakePHP est basé sur une architecture de type MVC à la fois puissante et facile à appréhender. Modèles, vues et contrôleurs gu

Pour travailler sur le téléchargement de fichiers, nous allons utiliser l'assistant de formulaire. Voici un exemple de téléchargement de fichiers.

Visual Studio Code, également connu sous le nom de VS Code, est un éditeur de code source gratuit – ou environnement de développement intégré (IDE) – disponible pour tous les principaux systèmes d'exploitation. Avec une large collection d'extensions pour de nombreux langages de programmation, VS Code peut être c

CakePHP est un framework MVC open source. Cela facilite grandement le développement, le déploiement et la maintenance des applications. CakePHP dispose d'un certain nombre de bibliothèques pour réduire la surcharge des tâches les plus courantes.

Ce tutoriel montre comment traiter efficacement les documents XML à l'aide de PHP. XML (Language de balisage extensible) est un langage de balisage basé sur le texte polyvalent conçu à la fois pour la lisibilité humaine et l'analyse de la machine. Il est couramment utilisé pour le stockage de données et

JWT est une norme ouverte basée sur JSON, utilisée pour transmettre en toute sécurité des informations entre les parties, principalement pour l'authentification de l'identité et l'échange d'informations. 1. JWT se compose de trois parties: en-tête, charge utile et signature. 2. Le principe de travail de JWT comprend trois étapes: la génération de JWT, la vérification de la charge utile JWT et l'analyse. 3. Lorsque vous utilisez JWT pour l'authentification en PHP, JWT peut être généré et vérifié, et les informations sur le rôle et l'autorisation des utilisateurs peuvent être incluses dans l'utilisation avancée. 4. Les erreurs courantes incluent une défaillance de vérification de signature, l'expiration des jetons et la charge utile surdimensionnée. Les compétences de débogage incluent l'utilisation des outils de débogage et de l'exploitation forestière. 5. L'optimisation des performances et les meilleures pratiques incluent l'utilisation des algorithmes de signature appropriés, la définition des périodes de validité raisonnablement,

Une chaîne est une séquence de caractères, y compris des lettres, des nombres et des symboles. Ce tutoriel apprendra à calculer le nombre de voyelles dans une chaîne donnée en PHP en utilisant différentes méthodes. Les voyelles en anglais sont a, e, i, o, u, et elles peuvent être en majuscules ou en minuscules. Qu'est-ce qu'une voyelle? Les voyelles sont des caractères alphabétiques qui représentent une prononciation spécifique. Il y a cinq voyelles en anglais, y compris les majuscules et les minuscules: a, e, i, o, u Exemple 1 Entrée: String = "TutorialSpoint" Sortie: 6 expliquer Les voyelles dans la chaîne "TutorialSpoint" sont u, o, i, a, o, i. Il y a 6 yuans au total
