IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Algorithme de Luhn


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 5
    Par défaut Algorithme de Luhn
    Bonjour à tous.

    L'algorithme de Luhn permet de tester la validité d'un code chiffré, en utilisant une méthode de vérification de somme (checksum). Il est utilisé par exemple pour certifier les codes de carte de crédit.

    Mon but est d'implémenter cet algo en langage C++ ; en m'aidant des docs de la toile (notament Wikipedia), j'ai écrit le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    int checkLuhn (char* code)
    {
    	int length, digit, sum, i ;
    	length = strlen(code) - 1 ;
     
    	// on parcourt tous les chiffres de droite à gauche..
    	for (i = length ; i >= 0 ; i--)
    	{
    		digit = code[i] ;
     
    		// si le rang <i> est pair (<i> XOR 1)..
    		if (i ^ 1)
    		{
    			// on double le chiffre placé au rang <i>..
    			digit *= 2 ;
     
    			// et si le chiffre est alors supérieur à 9, on fait la somme des chiffres (ex: 14 = 1+4 = 5)..
    			if (digit > 9)
    				digit -= 9 ;
    		}	
     
    		// on accumule enfin chaque chiffre "modifié"
    		sum += digit ;						
    	}
     
     	// si le résultat final est divisible par 10, retourne 1, sinon 0
    	return sum % 10 < 1 ;
    }
    L'ennui, c'est que, comme le sentiez venir, ce code ne semble pas fonctionnel.
    Lorsque, par exemple, je teste cette fonction avec le nombre 8763 (code qui devrait être validé par l'algo), j'ai un code de retour nul (en clair le code n'est pas validé).

    Je ne comprend pas d'où viens l'erreur ; algo mal transcrit, erreur de syntaxe [...] ?
    Je sollicite donc votre aide.

    Merci d'avance.

  2. #2
    Membre émérite
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Par défaut
    Bonjour et bienvenue sur les forums de Developpez

    Je t'avoue que je n'ai pas regardé ton code en détail car je présume que tu connais l'algo mais à la dernière ligne, au niveau du return, il manque peut-être des parenthèses dans la mesure où les opérateurs de comparaisons (<,>,==, ...) sont prioritaires sur les opérateurs +,-,*,/,...% .
    Pour faire plus simple, tu peux juste faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // si le résultat final est divisible par 10, retourne 1, sinon 0
    return (sum % 10) ? 0 : 1 ;
    Nas'

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 5
    Par défaut
    Merci pour l'accueil.. et pour l'astuce, je ne connaissais pas cette syntaxe.

    Quoi qu'il en soit, ça ne modifie pas l'issue (mauvaise) du code ; pour être sûr, j'avais auparavant essayé avec un if-then-else classique pour la valeur de retour (d'abord on code avec ce qu'on connait, et quand ça marche on optimise..).

    Par contre, je viens de me rendre compte que ce code ne marcherais qu'avec un code dont le nombre de chiffre est pair.. pour la robustesse, c'est pas génial, mais peu importe puisque pour l'instant je ne teste qu'avec mon numéro de carte..

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // si le rang <i> est pair (<i> XOR 1)...
    if (i ^ 1)
    {
      ...
    ça ne serait pas plutôt "if ( i % 2 == 0 )" ? parce que là, avec le xor et, par exemple, i = 3, on aura 11b ^ 01b == 10b > 0 et le test sera validé...

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 5
    Par défaut
    Le XOR compare ici le bit de poids faible (premier en partant de la droite) de mon rang i avec 1.. enfin je crois ! L'opérateur modulo fonctionne aussi, mais le processeur fait une opération de plus. (J'ai quand même essayé avec ce dernier, sans plus de succès qu'auparavant)

  6. #6
    Invité
    Invité(e)
    Par défaut
    Utilise le "et binaire" dans ce cas, noté &, et non le ou exclusif binaire, noté ^

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Par défaut
    Bonjour,

    moi je me demande s'il faudrait pas aussi initialiaser sum ...
    il a l'air trés gros sum ...

    Une solution détaillée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    int checkLuhn (char* code)
    {
    	int length, digit, sum, i ;
    	length = strlen(code) ;
     
    	sum = 0;
     
    	// on parcourt tous les chiffres de droite à gauche..
    	for (i = 0 ; i < length; i++)
    	{
    		digit = code[i]-48;
     
    		// si le rang <i> est pair (<i> XOR 1)..
    		if ((i & 1) == 0)
    		{
    			// on double le chiffre placé au rang <i>..
    			digit *= 2 ;
     
    			// et si le chiffre est alors supérieur à 9, on fait la somme des chiffres (ex: 14 = 1+4 = 5)..
    			if (digit > 9)
    				digit -= 9 ;
    		}	
     
    		// on accumule enfin chaque chiffre "modifié"
    		sum += digit ;						
    	}
     
     	// si le résultat final est divisible par 10, retourne 1, sinon 0
    	return (sum % 10) ? 0 : 1 ;
    }
    sinon, avec moins de lignes de code :
    http://blogs.media-tips.com/bernard....5e2f9215e.aspx



    @+

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 5
    Par défaut
    Effectivement, ton code marche. Grand merci à toi, le malin !

    Par contre, si tu pouvais juste m'éclairer sur cette ligne :
    (Pourquoi soustraire 48 ?)

    Et pourquoi est-il nécéssaire d'initialiser mon objet 'sum' ?

    Le lien que tu m'a passé est un vrai modèle d'optimisation, mais pour l'instant je préfère m'en tenir à des codes un peu plus détaillés et compréhensibles !

  9. #9
    Membre averti
    Inscrit en
    Avril 2005
    Messages
    38
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 38
    Par défaut
    Salut !
    En fait il est nécéssaire d'initialiser la variable sum avant de l'incrémenter directement car à cette endroit en mémoire il y avait probablement de la "scrap" et probablement pas 0... Donc si il y avait 9128841 à cette endroit avant que tu réserve cette plage pour ton int sum, bah tu ajoute digit à 9128841, c'est donc pour ca qu'il faut le partir à zéro... Tu n'aurais pas ce problème en C#. Mais en C++ à des fins de performances, le contructeur par défaut du int n'est pas appelé. (on me corrige si j'ai tord.)

    Et ensuite le -48, vient du code ASCII ... 0 en ASCII c'est 48, 1 c'est 49, 2 c'est 50 ... Tu te doutes surement de la suite... donc pour obtenir réellement 3 (qui est 51 en ASCII) alors tu dois soustraire 48...

    Voilà ! Longue vie à toi !.

    Yannick

  10. #10
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 287
    Par défaut
    Ah .. les joies de l'obfuscation ...
    s/48/'0'/
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 5
    Par défaut
    Citation Envoyé par YmYannick
    Et ensuite le -48, vient du code ASCII ... 0 en ASCII c'est 48, 1 c'est 49, 2 c'est 50 ... Tu te doutes surement de la suite... donc pour obtenir réellement 3 (qui est 51 en ASCII) alors tu dois soustraire 48...
    Aah oui, bien sûr.. Elementaire, mon cher !

    C'est un problème résolu, je crois.

    Merci à tous pour vos éclaircissements, et à bientôt !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Algorithme de LUHN
    Par DelphiCool dans le forum Codes sources à télécharger
    Réponses: 0
    Dernier message: 03/02/2013, 17h24
  2. Algorithme de randomisation ... ( Hasard ...? )
    Par Anonymous dans le forum Assembleur
    Réponses: 8
    Dernier message: 06/09/2002, 14h25
  3. recherches des cours ou des explications sur les algorithmes
    Par Marcus2211 dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 19/05/2002, 22h18
  4. Recherche de documentation complète en algorithmes
    Par Anonymous dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 29/03/2002, 12h09
  5. Algorithme génétique
    Par Stephane.P_(dis Postef) dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 15/03/2002, 17h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo