fonction de Luhn en php

Après avoir regarder du côté de wikipédia, j’ai pu construire la fonction de Luhn permettant entre autre de vérifier des numéros de carte bancaire.

//Fonction algorithme de Luhn
function isLuhnNum($num)
{
	//longueur de la chaine $num
	$length = strlen($num);
	
	//resultat de l'addition de tous les chiffres
	$tot = 0;
	for($i=$length-1;$i>=0;$i--)
	{
		$digit = substr($num, $i, 1);
		
		if ((($length - $i) % 2) == 0)
		{
			$digit = $digit*2;
			if ($digit>9)
			{
				$digit = $digit-9;
			}
		}
		$tot += $digit;
	}
	
	return (($tot % 10) == 0);
}

Merci à Andras pour sa précision 😉


Commentaires

8 réponses à “fonction de Luhn en php”

  1. Avatar de Xfigpower
    Xfigpower

    Moi, j’utilise perso une version plus courte (je n’aime pas beaucoup le « -9 » dans l’algo)

    //Fonction algorithme de Luhn
    function isCB($numCB)
    {
    //longueur de la chaine $numCB
    $lengthCB = strlen($numCB);

    //resultat de l’addition de tous les chiffres
    $tot = 0;

    for($i=$lengthCB-1;$i>=0;$i–)
    {
    $digit = $numCB[$i];

    $tot += ($i % 2)?((2*$digit)%10 + (2*$digit)/10):$digit;
    }

    return !($tot % 10);
    }

  2. Moi c’est le (2*$digit)/10 qui me gène, ça donne forcément un float lorsque tu fais par exemple $digit = 1; Si tu travailles comme ça dans un autre language tel que Java ou C# ça ne passera jamais. Bon il est vrai que là on est censé recevoir un int et qu’on l’interprète comme un string donc bon…

    Le -9 est déjà plus mathématique car on a forcément un chiffre compris entre 0 et 18 lorsqu’on multiplie par 2 $digit et qu’il correspond exactement à ce que l’algorithme doit faire.

    C’est clair, c’est plus rapide, mais pas à comprendre pour un néophyte…

  3. hum, il me semble bien qu’il y a une erreur dans ton implementation : ça ne marche qu’avec les nombres qui ont un nombre de chiffre pair (comme les CB) mais pas avec ceux qui ont un nombre de chiffres impair (comme les numéros SIREN).

    il faut remplacer la ligne :
    if (($i % 2) == 0)
    par la ligne suivante :
    if ((($length – $i) % 2) == 0)

    et là, ça marche pour tous les cas, il me semble.

  4. Merci pour cette précision Andras 😉

  5. Francis Hilaire :
    J’ai eu du mal à voir du premier coup comment circule la variable « $ret » tout au long de ton programme, pourquoi ne pas utiliser tout simplement :
    return ($tot % 10 == 0);

    As-tu une raison particulière d’appeler la fonction « substr » au lieu de l’opérateur « crochets » ?
    $digit = $num[$i];

    Xfigpower :
    Je paraphrase Francis Hilaire en ajoutant que la division est généralement l’opération de base la plus couteuse en temps processeur (quelque soit le language ou le processeur utilisé). Pire, ta multiplication par 2 est effectuée deux fois de suite pour rien !

  6. Melnofil : Merci de ton intervention, j’avoue que c’est l’habitude qui m’as fait mettre ce $ret… Il est vrai qu’il est complètement inutile.

  7. Intéressant : en cas de paramètre vide, la fonction renvoie quand même true.
    [ isLuhnNum( ») => true ]

    Penser à ajouter ceci en début de fonction pour remédier simplement au problème


    if($length==0){
    return false;
    }

  8. @Poulpos : Ce n’est qu’un court code très ciblé que vous pouvez modifier et réutiliser, il n’est pas destiné à contrôler autre chose que la validité d’une chaîne de caractère qui aura dut être contrôlée en amont par vos différents validateurs de saisies.

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.