Calculer une moyenne

Eléphanteau du PHP | 15 Messages

16 mars 2013, 19:24

Bonjour
J'ai des variables issues d'un fichier mysql en VARCHAR,
Je voudrai faire une moyenne des notes avec $moy= ($CFG1FR+ $CFG1MA+ $CFG2FR+ $CFG2MA+ $CFG3FR+ $CFG3MA + $CFG1ORAL)/7;
Le problème est que mes données si elles sont vides c.-à-d. Rien, sont considèrées comme étant égale à zéro donc la moyenne de mes notes est faussée....
J'avais essayé avec un format décimal mais idem...
Une idée ?
Merci

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

16 mars 2013, 21:38

Bonjour, tu dois compter les champs non vides pour déterminer le nombre à utiliser pour la division dans la moyenne.
Voici une proposition de correction :
//fonction qui compte de nombre d'éléments non vides dans un tableau
function nb_non_vide($liste_nombres) {
    $nb = 0;
    if (is_array($liste_nombres)) foreach($liste_nombres as $nombre){
          $nb += empty($nombre) ? 0 : 1;
    }
    return $nb;
}

//utilisation de la fonction pour calculer la moyenne
$nb = nb_non_vide( array($CFG1FR, $CFG1MA, $CFG2FR, $CFG2MA, $CFG3FR, $CFG3MA , $CFG1ORAL) );
$moy = ($CFG1FR+ $CFG1MA+ $CFG2FR+ $CFG2MA+ $CFG3FR+ $CFG3MA + $CFG1ORAL) / $nb;
On peut aussi dédier le calcul de la moyenne à la fonction comme ça:
//fonction qui calcule la moyenne des nombres non nuls d'un tableau
function moyenne($liste_nombres) {
    $nb = 0; $somme = 0;
    if (is_array($liste_nombres)) foreach($liste_nombres as $nombre){
          $nb += empty($nombre) ? 0 : 1;
          $somme += floatval ($nombre);
    }
    return ($somme/$nb);
}

//utilisation de la fonction pour calculer la moyenne
$moy = moyenne( array($CFG1FR, $CFG1MA, $CFG2FR, $CFG2MA, $CFG3FR, $CFG3MA , $CFG1ORAL) );
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Eléphanteau du PHP | 15 Messages

16 mars 2013, 22:46

Merci
Comme je ne suis pas un spécialiste des fonctions, je tâtonne...
J'ai un Parse error: syntax error, unexpected T_FOREACH in /homepages/ a la ligne
if (is_array($liste_nombres) foreach($liste_nombres as .....
Et la je sèche.
:lol:

ViPHP
ViPHP | 1996 Messages

16 mars 2013, 23:16

il manque une )
function nb_non_vide($liste_nombres) {
    $nb = 0;
    if (is_array($liste_nombres))
        foreach($liste_nombres as $nombre) 
            $nb += empty($nombre) ? 0 : 1;
    
    return $nb;
}
It is nice to be important but it is more important to be nice
http://www.aureuswebfactory.fr

Eléphanteau du PHP | 15 Messages

16 mars 2013, 23:31

Cela n'a pas l'air de fonctionner, j'ai toujours une mauvaise moyenne.
Voici mon code entier, soyez indulgents sur le code, je suis un vrai branquignole.... :oops:
<?php
error_reporting(0); //N'affiche pas les erreurs d'encodage impossible
header("Content-type: text/html; charset=ISO-8859-1");
echo "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
include("./ges_includes/variables.inc.php");
include("./ges_includes/haut.inc.php");

$liendb = mysql_connect($bddserver, $bddlogin, $bddpassword);
mysql_select_db ($bdd);
if (isset($_POST['motclef']))
     $motclef = $_POST['motclef'];
 
function donne_age($date_naissance) {
    $date_encours = date("d/m/Y");
    $array1 = explode("/", $date_naissance);
    $array2 = explode("/", $date_encours);
    
    // $arrayX[0] = jour;
    // $arrayX[1] = mois;
    // $arrayX[2] = année;
    
    if (($array1[1] <= $array2[1]) && ($array1[0] <= $array2[0])) {
        $age = $array2[2] - $array1[2];
    } else {
        $age = $array2[2] - $array1[2] - 1;
    }
    echo $age." ans";
}


?> 


<?php
// code pour compter
$req2 = mysql_query("SELECT * FROM `ELEVES3`");          
$res2 = mysql_num_rows($req2);                               
echo '<br>';
echo '<br>';
echo 'Il y a '.$res2.' élèves.';  
// fin du code apour compter

?> 


<p align="center"> GESTION DU CFG</p>
  

<table width="90%" align="center" border="1">
 <tr>
   <td class="intitule">Classe</td>
 <td class="intitule">Nom</td>
 <td class="intitule">Prénom</td>
 <td class="intitule">Date Naissance</td>
  <td class="intitule">T1</td>
  <td class="intitule">T2</td>
  <td class="intitule">T3</td>
  <td class="intitule">T2 Ch 1</td>
  <td class="intitule">T2 Ch 2</td>
  <td class="intitule">T2 Ch 3</td>
  <td class="intitule">CFG</td>
  <td class="intitule">1/3</td>
<td class="intitule">CFG1_FR</td>
<td class="intitule">CFG1_MA</td>
<td class="intitule">CFG2_FR</td>
<td class="intitule">CFG2_MA</td>
<td class="intitule">CFG3_FR</td>
<td class="intitule">CFG3_MA</td>
<td class="intitule">CFG1_ORAL</td>
<td class="intitule">MOY GEN</td>
 </tr>
	
<?php


$sql = "SELECT * FROM ELEVES3 WHERE CFG like 'O' ORDER BY Code_Structure, NOM"; 
$resultat = mysql_query ($sql);
echo $sql;
$rest = mysql_num_rows($resultat);                               
echo '<br>';
echo 'Il y a '.$rest.' élèves.';

while ($eleve = mysql_fetch_array ($resultat))
{
 $id = $eleve['Eleve_No_Etab'];
 $cla= $eleve['Code_Structure'];
 $nom = $eleve['Nom'];
 $prenom = $eleve['Prenom'];
 $date = $eleve['Date_Naissance'];
 $T1 = $eleve['T1'];
  $T2 = $eleve['T2'];
   $T3 = $eleve['T3'];
   $CHOIX1 = $eleve['CH1_T2'];
   $CHOIX2 = $eleve['CH2_T2'];
   $CHOIX3 = $eleve['CH3_T2'];
   $cfg = $eleve['CFG'];
   $tt = $eleve['TTemps'];
   $CFG1FR = $eleve['CFG1_FR'];
   $CFG1MA = $eleve['CFG1_MA'];
   $CFG2FR = $eleve['CFG2_FR'];
   $CFG2MA = $eleve['CFG2_MA'];
   $CFG3FR = $eleve['CFG3_FR'];
   $CFG3MA = $eleve['CFG3_MA'];
   $CFG1ORAL = $eleve['CFG1_ORAL'];
   
   
   //fonction qui calcule la moyenne des nombres non nuls d'un tableau
function moyenne($liste_nombres) {
    $nb = 0; $somme = 0;
    if (is_array($liste_nombres)) foreach($liste_nombres as $nombre){
          $nb += empty($nombre) ? 0 : 1;
          $somme += floatval ($nombre);
    }
    return ($somme/$nb);
}

//utilisation de la fonction pour calculer la moyenne
$moy = moyenne( array($CFG1FR, $CFG1MA, $CFG2FR, $CFG2MA, $CFG3FR, $CFG3MA , $CFG1ORAL) );
echo "<br>";
 echo $moy;

 echo "<tr>";
 
 $moy= ($CFG1FR+ $CFG1MA+ $CFG2FR+ $CFG2MA+ $CFG3FR+ $CFG3MA + $CFG1ORAL)/7;
//echo ROUND($moy,2);
$moya=ROUND($moy,2);

 //echo "<td>$id</td>";
 echo "<td>$cla</td>";
 echo "<td><B>$nom</td>";
 echo "<td>$prenom</td>";
 echo "<td>$date</td>";
  echo "<td>$T1</td>";
  echo "<td>$T2</td>";
   echo "<td>$T3</td>";
   echo "<td>$CHOIX1</td>";
   echo "<td>$CHOIX2</td>";
   echo "<td>$CHOIX3</td>";
   echo "<td>$cfg</td>";
   echo "<td>$tt</td>";
   echo "<td>$CFG1FR</td>";
   echo "<td>$CFG1MA</td>";
   echo "<td>$CFG2FR</td>";
   echo "<td>$CFG2MA</td>";
   echo "<td>$CFG3FR</td>";
   echo "<td>$CFG3MA</td>";
   echo "<td>$CFG1ORAL</td>";
   echo "<td>$moya</td>";
   

 //echo "<a href=eleve_edite.php?id=$id>JOURNAL</a>";
 echo "<td>";
 echo "<a href=eleve_edite.php?id=$id>Journal</a>";


  //echo "<a href=imprimersanctionsimple.php?id=$id>imprimer LA FICHE</a>";
  echo "</td>";

}

echo "</table>";
mysql_close($liendb);
include("../bas.inc.php");

?>




ViPHP
ViPHP | 1996 Messages

17 mars 2013, 00:03

Bonjour,

J'ai remodeler à ma sauce.
function moyenne($tableau) 
{
    if (!is_array($tableau) or empty($tableau)) 
		return FALSE;
	
	$nb = count($tableau);
	$total = 0;
	foreach($tableau as $nombre)
	{
		if (filter_var($nombre,FILTER_VALIDATE_FLOAT) or (filter_var($nombre,FILTER_VALIDATE_INT))
			$total += floatval($nombre);
		else
			$nb--;
	}
	
	if ($nb <= 0)
		return FALSE;
	else
	   return (array($total,$nb));
}
Alors, j'explique la fonction :
 if (!is_array($tableau) or empty($tableau)) 
		return FALSE;
Si pas tableau ou tableau vide => retourne faux
$nb = count($tableau);
	$total = 0;
	foreach($tableau as $nombre)
	{
		if (filter_var($nombre,FILTER_VALIDATE_FLOAT) or (filter_var($nombre,FILTER_VALIDATE_INT))
			$total += floatval($nombre);
		else
			$nb--;
	}
Je compte le nombre d'occurence dans le tableau avec $nb = count($tableau);
Je boucle sur le tableau avec foreach($tableau as $nombre) et si par filter_var($nombre,FILTER_VALIDATE_FLOAT) or (filter_var($nombre,FILTER_VALIDATE_INT)) $nombre n'est ni un décimal, ni un nombre entier alors avec $nb-- je retire l'occurrence du nombre total sinon j'ajoute au total la valeur formatée en nombre décimal avec $total += floatval($nombre);

Ensuite avec
if ($nb <= 0)
		return FALSE;
Si toutes les occurences sont fausse => retourne faux (car on ne peut pas diviser par zéro) sinon avec return (array($total,$nb)); je retourne un tableau avec le total et le nombre d'occurences.

Ce mode de retour te permet de vérifier le total et le nombre d'occurence (pour vérifier la fonction.
Aussi pour l'utiliser tu dois lister les deux valeurs retournées pas la fonction et en même temps si aucune erreur survient :
if ($tab = moyenne( array($CFG1FR, $CFG1MA, $CFG2FR, $CFG2MA, $CFG3FR, $CFG3MA , $CFG1ORAL) ))
{
	list ($total,$nb) = $tab;
	$moyenne = $total/$nb;
	echo "Total = ".$total." Nombre = ".$nb." Moyenne = ".$moyenne;
}
else
	echo 'erreur dans la fonction "moyenne"';
list() est une pseudo fonction qui prends les "colonnes" d'un tableau et les mets dans la variable listée. Comme ici list ($total,$nb) = $tab; et que normallemnt $tab = array($total,$nb); alors $total = $total (mais de la fonction) et $nb = $nb (mais de la fonction)
It is nice to be important but it is more important to be nice
http://www.aureuswebfactory.fr

Eléphanteau du PHP | 15 Messages

17 mars 2013, 13:31

Merci pour l'explication et le code, c'est un peu plus clair et très peda.
Par contre j'ai toujours un
Parse error: syntax error, unexpected T_VARIABLE
À la ligne
$total += floatval($nombre);

Eléphant du PHP | 120 Messages

17 mars 2013, 16:11

Faut dire que ce code est très crade aussi. À vouloir mettre des parenthèses inutiles et à retirer des accolades qui servent à la clarté de la structuration du code, on produit vite du code syntaxiquement faux.
function moyenne(array $valeurs) {
    $valeurs = filter_var_array($valeurs, FILTER_VALIDATE_FLOAT);
    $nb = 0;
    $somme = 0.0;
    foreach ($valeurs as $valeur) {
        if ($valeur !== false /* || $valeur === 0.0 */) {
            $somme+= $valeur;
            ++$nb;
        }
    }
    if ($nb === 0) {
        throw new \Exception("Aucune valeur correcte donnée.");
    }
    return $somme / $nb;
}
Si des valeurs qui sont des nombres égaux à 0 et que tu veux les exclure, il faut que tu supprimes le commentaire dans la boucle.

ViPHP
ViPHP | 1996 Messages

17 mars 2013, 21:19

Faut dire que ce code est très crade aussi.
@Perine, ca fais toujours plaisir d'aider... En plus je ne vois pas où le code n'est pas clair... Enfin bref, différente technique, différent point de vues...
@Pasbonte, il manquait juste une parenthèse (encore une :) ) même si c'est "crade". J'espère seulement que tu as compris un peu la démarche et la logique
if (filter_var($nombre,FILTER_VALIDATE_FLOAT) or (filter_var($nombre,FILTER_VALIDATE_INT)) )
@Perine, excellent code pour "Php Avancé" mais je ne pense pas vu le niveau de la demande qu'il puisse gérer les exceptions. :D Très beau code quand même.

J'ajouterai (car tu m'a piqué un peu au vif :o Et en plus cela fais un peu avancé le débat technique, j'aime) un test pour voir si la fonction filter_var_array() retourne une erreur ou pas.
Une petite chose néanmoins : comme je ne connaissais pas cette fonction, je me suis documenté. J'ai vu que les valeurs pouvaient, avec le filtre choisi, soit retourner un nombre décimal (le but recherché) , soit retourné False (si pas décimal), soit NULL si la variable n'est pas définie. Aussi vu que tu test avec $valeur !== false, je pense que les valeurs Null, si elles existent, seront oubliées et retourneront "true". Or ici, il ne s'agit pas de valeurs numériques.
De même, je ne connaissais pas cette notation $b === 0 sur des valeurs numériques. Pour moi "===" indique "identique en valeur et en genre". Pour moi (mais je peux me tromper), $b == 0 suffirait. Isn't it ?
It is nice to be important but it is more important to be nice
http://www.aureuswebfactory.fr

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

17 mars 2013, 21:34

Bonjour, Commence par enlever cette ligne car tu l'as laissé après le calcul avec la fonction moyenne. Ce qui te recalcule la mauvaise moyenne.
$moy= ($CFG1FR+ $CFG1MA+ $CFG2FR+ $CFG2MA+ $CFG3FR+ $CFG3MA + $CFG1ORAL)/7;
En principe mon code fonctionne parfaitement (à part que j'ai oublié une parenthèse du if) voici une nouvelle version où j'ai ajouté une condition is_numeric() pour ne traiter que les numériques. Et voici le test qui fonctionne bien :
<?php
//fonction qui calcule la moyenne des nombres non nuls d'un tableau
function moyenne($liste_nombres) {
    $nb = 0; $somme = 0;
    if (is_array($liste_nombres)) foreach($liste_nombres as $nombre){
          $nb += empty($nombre)||!is_numeric($nombre) ? 0 : 1;
          $somme += floatval ($nombre);
    }
    return $nb!=0 ? ($somme/$nb) : 0;
}

//utilisation de la fonction pour calculer la moyenne
$moy = moyenne( array($CFG1FR, $CFG1MA, $CFG2FR, $CFG2MA, $CFG3FR, $CFG3MA , $CFG1ORAL) );
?>
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène