par
zeus » 20 juil. 2009, 01:05
Bonjour,
La méthodologie pour pondérer une probabilité (c'est à dire fixer un pourcentage de sortie), c'est de faire apparaitre plusieurs fois chaque résultat, en fonction de la pondération.
Par exemple, voici un jeu de résultat, avec une pondération :
Code : Tout sélectionner
+---------+-------------+
| valeur | pondération |
+---------+-------------+
| valeur1 | 20% |
| valeur2 | 30% |
| valeur3 | 50% |
+---------+-------------+
Si tu fais une requête simple de choix aléatoire, telle que la suivante :
Dans ce cas, il y a 1 chance sur 3 pour chaque valeur qu'elle sorte. Ceci parce qu'il y a 3 valeurs dans le résultat du SELECT, et le ORDER BY RAND() choisie aléatoirement une valeur du résultat.
Pour pondérer le résultat, il faut que tu dupliques les valeurs dans le résultat, avant d'appliquer la sélection aléatoire.
Je m'explique : dans le jeu de test que je t'ai donné ci-dessus, je veux que la valeur1 n'ait que 20% de chance de sortir. Il faut donc que je me débrouille pour qu'elle représente 20% des résultats dans lequel la sélection aléatoire va se faire.
Pour cela, il faut que je fasse apparaitre 2 fois dans le jeu de résultat, qui devra contenir 10 lignes.
Pour la valeur2, en suivant la même logique, il faut qu'elle apparaisse 3 fois, et pour la valeur3, 5 fois.
Au final, je vais obtenir un jeu de possibilité semblable à ça :
Code : Tout sélectionner
valeur1
valeur1
valeur2
valeur2
valeur2
valeur3
valeur3
valeur3
valeur3
valeur3
Maintenant, sur ce résultat, je peux appliquer une sélection aléatoire standard, et je sais que j'ai appliqué une pondération aux votes puisque qu'il n'y a que 20% (2 chances sur 10) que la valeur1 soit choisie.
J'ai pour habitude de faire ce genre de traitement en PHP, parce que je trouve que la solution tout SQL est assez lourde pour le SGBD.
Voici ce que je ferais :
<?php
/**
* Basé sur le schéma suivant :
*
* CREATE TABLE `phpfrance`.`valeurs` (
* `id_valeur` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
* `nom` VARCHAR( 255 ) NOT NULL ,
* `ponderation` INT NOT NULL ,
* PRIMARY KEY ( `id_valeur` )
* ) ENGINE = InnoDB
*/
// Exemple de connexion à une base MySQL
$dbh = new PDO('mysql:host=localhost;dbname=phpfrance', 'root', 'password');
$str_requete = 'SELECT nom, ponderation FROM valeurs';
$a_results = array();
// On parcours la liste des résultats
foreach( $dbh->query($str_requete) as $a_valeur )
{
// On ajoute autant de fois la valeur que la pondération l'indique
for($i = 0; $i < $a_valeur['ponderation']; $i++)
$a_results[] = $a_valeur['nom'];
}
// Et maintenant, on récupére une valeur aléatoirement dans ce tableau
$gagnant = $a_results[array_rand($a_results)];
echo "Et le gagnant est '".$gagnant."'";
Bonjour,
La méthodologie pour pondérer une probabilité (c'est à dire fixer un pourcentage de sortie), c'est de faire apparaitre plusieurs fois chaque résultat, en fonction de la pondération.
Par exemple, voici un jeu de résultat, avec une pondération :
[code]+---------+-------------+
| valeur | pondération |
+---------+-------------+
| valeur1 | 20% |
| valeur2 | 30% |
| valeur3 | 50% |
+---------+-------------+[/code]
Si tu fais une requête simple de choix aléatoire, telle que la suivante :
[code]SELECT * FROM laTable ORDER BY RAND() LIMIT 1[/code]
Dans ce cas, il y a 1 chance sur 3 pour chaque valeur qu'elle sorte. Ceci parce qu'il y a 3 valeurs dans le résultat du SELECT, et le ORDER BY RAND() choisie aléatoirement une valeur du résultat.
Pour pondérer le résultat, il faut que tu dupliques les valeurs dans le résultat, avant d'appliquer la sélection aléatoire.
Je m'explique : dans le jeu de test que je t'ai donné ci-dessus, je veux que la valeur1 n'ait que 20% de chance de sortir. Il faut donc que je me débrouille pour qu'elle représente 20% des résultats dans lequel la sélection aléatoire va se faire.
Pour cela, il faut que je fasse apparaitre 2 fois dans le jeu de résultat, qui devra contenir 10 lignes.
Pour la valeur2, en suivant la même logique, il faut qu'elle apparaisse 3 fois, et pour la valeur3, 5 fois.
Au final, je vais obtenir un jeu de possibilité semblable à ça :
[code]valeur1
valeur1
valeur2
valeur2
valeur2
valeur3
valeur3
valeur3
valeur3
valeur3[/code]
Maintenant, sur ce résultat, je peux appliquer une sélection aléatoire standard, et je sais que j'ai appliqué une pondération aux votes puisque qu'il n'y a que 20% (2 chances sur 10) que la valeur1 soit choisie.
J'ai pour habitude de faire ce genre de traitement en PHP, parce que je trouve que la solution tout SQL est assez lourde pour le SGBD.
Voici ce que je ferais :
[php]<?php
/**
* Basé sur le schéma suivant :
*
* CREATE TABLE `phpfrance`.`valeurs` (
* `id_valeur` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
* `nom` VARCHAR( 255 ) NOT NULL ,
* `ponderation` INT NOT NULL ,
* PRIMARY KEY ( `id_valeur` )
* ) ENGINE = InnoDB
*/
// Exemple de connexion à une base MySQL
$dbh = new PDO('mysql:host=localhost;dbname=phpfrance', 'root', 'password');
$str_requete = 'SELECT nom, ponderation FROM valeurs';
$a_results = array();
// On parcours la liste des résultats
foreach( $dbh->query($str_requete) as $a_valeur )
{
// On ajoute autant de fois la valeur que la pondération l'indique
for($i = 0; $i < $a_valeur['ponderation']; $i++)
$a_results[] = $a_valeur['nom'];
}
// Et maintenant, on récupére une valeur aléatoirement dans ce tableau
$gagnant = $a_results[array_rand($a_results)];
echo "Et le gagnant est '".$gagnant."'";[/php]