For­mule de Luhn

For­mule de Luhn

sam 16 février 2019 0 Par Ibmiiste

Petite défi­ni­tion de la Luhn

La for­mule de Luhn per­met de véri­fier la vali­di­té d’une suite de chiffre. Ex:SIREN, N°CB, N°PS (Méde­cin pra­ti­cien, etc…). Le nombre est lu de droite à gauche. Les chiffres en posi­tion impaire res­tent tel quel et les chiffres en posi­tion paire sont mul­ti­pliées par 2. Tous les chiffres résul­tants sont ajou­tés. Exemple 456 : 

Chiffres       4             5           6 
Position     3             2           1
Résultats     4 10 6
Résultat 4 + 1 + 0 + 6 = 11

Un nombre Luhn est vali­dé si le résul­tat est divi­sible par 10. Dans l’exemple pré­cé­dent, le nombre n’est pas valide ; 11 n’est pas divi­sible par 10. Un nombre valide est par exemple 455. 

Coding

Voi­ci ci-des­sous, une pro­cé­dure écrite pour véri­fier un nombre selon la for­mule de Luhn. Elle est com­po­sée d’une pro­cé­dure prin­ci­pale et 2 sous-procédures. 

La sous-pro­cé­dure CALCUL déter­mine le résul­tat des addi­tions suc­ces­sives. Remarque : dans le cas du cal­cul des posi­tions paires, une autre règle a été appli­quée sur les résul­tats supé­rieurs à 9. La somme des chiffres obte­nus est égale à la mul­ti­pli­ca­tion par 2 moins 9. 

5x2=10 Résultat 1+0=1 mais aussi 5x2-9=1
6x2=12 Résultat 1+2=3 mais aussi 6x2-9=3
7x2=14 Résultat 1+4=5 mais aussi 7x2-9=5
8x2=16 Résultat 1+6=7 mais aussi 8x2-9=7
9x2=18 Résultat 1+8=9 mais aussi 9x2-9=9

La sous-pro­cé­dure PARITE déter­mine si un chiffre est pair ou impair. 

     h nomain

     dVerif_Luhn       PR              N
     d a_Nombre_Luhn              32768A   OPTIONS(*VARSIZE) CONST


     dCalcul           PR             6  0
     d a_Nombre_Luhn              32768A   OPTIONS(*VARSIZE) CONST

     d a_longueur                     5i 0

     D*--------------------------------------------------
     D* Procedure name: parite
     D* Purpose:        Déterminer si un nombre est pair ou impair
     D* Returns:
     D* Parameter:      a_nombre => Nombre dont on vérifie la parité
     D*--------------------------------------------------
     Dparite           PR              N
     D  a_nombre                      6P 0 value

     pVerif_Luhn       b                   Export
     dVerif_Luhn       PI              N
     dg_nbre_luhn                 32768A   OPTIONS(*VARSIZE) CONST

     d g_longueur      s              5i 0
     d g_valid         s              1  0
     d g_luhn          s               N
     d g_Nombre_Luhn   s             20A   Varying
      /free
       g_Nombre_Luhn=%trim(g_nbre_luhn);
       g_longueur=%len(%trim(g_Nombre_Luhn));
       g_valid=%rem( calcul(g_Nombre_Luhn:g_longueur):10);
       If g_valid=0;
         g_Luhn=*on;
       Else;
         g_Luhn=*off;
       ENDIF;
       Return g_Luhn;
      /end-free

     pVerif_Luhn       e

     pcalcul           b
     dCalcul           PI             6  0
     d l_Nombre_Luhn              32768A   OPTIONS(*VARSIZE) CONST
     d l_longueur                     5i 0

     d l_pos           s              5i 0
     d l_total         s              6  0
     d l_ajout         s              2  0

      /free

       FOR l_pos = l_longueur DOWNTO 1;
       // Le corps de la boucle va ici
         l_ajout=%dec(%subst(l_Nombre_Luhn:l_pos:1):2:0);
         if parite(l_pos);
           l_ajout=l_ajout*2;
           if l_ajout>9;
             l_ajout=l_ajout-9;
           ENDIF;
         ENDIF;
         l_total=l_total+l_ajout;
       ENDFOR;

       return l_total;
      /end-free

     pcalcul           e


     P*--------------------------------------------------
     P* Procedure name: parite
     P* Purpose:        Déterminer di un nombre est pair ou impair
     P* Returns:
     P* Parameter:      a_nombre => Nombre dont on vérifie la parité
     P*--------------------------------------------------
     P parite          B
     D parite          PI              N
     D  l_nombre                      6P 0 value


     D* Local fields
     D l_reste         s              1  0
     d l_pair          s               N   inz(*off)

      /FREE

        l_reste= %rem( l_nombre:2);
        if l_reste=0;
          l_pair=*on;
        ENDIF;

        RETURN l_pair;

      /END-FREE
     P parite          E