Question

Il existe de nombreuses implémentations pour valider les sommes de contrôle de Luhn mais très peu pour les générer. J'ai rencontré celui-ci , mais il s'est révélé bogué lors de mes tests et je ne le fais pas. comprendre la logique de la variable delta.

J'ai créé cette fonction censée générer les sommes de contrôle Luhn mais, pour une raison quelconque, je n'ai pas encore compris que les sommes de contrôle générées sont invalides la moitié du temps.

function Luhn($number, $iterations = 1)
{
    while ($iterations-- >= 1)
    {
        $stack = 0;
        $parity = strlen($number) % 2;
        $number = str_split($number, 1);

        foreach ($number as $key => $value)
        {
            if ($key % 2 == $parity)
            {
                $value *= 2;

                if ($value > 9)
                {
                    $value -= 9;
                }
            }

            $stack += $value;
        }

        $stack = 10 - $stack % 10;

        if ($stack == 10)
        {
            $stack = 0;
        }

        $number[] = $stack;
    }

    return implode('', $number);
}

Quelques exemples:

Luhn(3); // 37, invalid
Luhn(37); // 372, valid
Luhn(372); // 3728, invalid
Luhn(3728); // 37283, valid
Luhn(37283); // 372837, invalid
Luhn(372837); // 3728375, valid

Je valide les totaux de contrôle générés par rapport à cette page . Qu'est-ce que je me trompe ici?

Pour référence future, voici la fonction de travail.

function Luhn($number, $iterations = 1)
{
    while ($iterations-- >= 1)
    {
        $stack = 0;
        $number = str_split(strrev($number), 1);

        foreach ($number as $key => $value)
        {
            if ($key % 2 == 0)
            {
                $value = array_sum(str_split($value * 2, 1));
            }

            $stack += $value;
        }

        $stack %= 10;

        if ($stack != 0)
        {
            $stack -= 10;
        }

        $number = implode('', array_reverse($number)) . abs($stack);
    }

    return $number;
}

J'ai abandonné la variable $ parity car nous n'en avons pas besoin pour cela et pour vérifier:

function Luhn_Verify($number, $iterations = 1)
{
    $result = substr($number, 0, - $iterations);

    if (Luhn($result, $iterations) == $number)
    {
        return $result;
    }

    return false;
}
Était-ce utile?

La solution

Modifier : Désolé, je sais maintenant que vous aviez déjà presque toute ma réponse, vous veniez de déterminer de manière erronée le facteur à utiliser pour quel chiffre.

Toute ma réponse peut maintenant se résumer à cette seule phrase:

Le facteur est inversé, vous multipliez les mauvais chiffres par 2 en fonction de la longueur du nombre.

Consultez l'article sur Wikipedia relatif à l'algorithme de Luhn .

Si votre somme de contrôle est invalide la moitié du temps, c’est que, dans vos chèques, le nombre de chiffres impairs est deux fois moins élevé, puis vous doublez le mauvais chiffre.

Pour 37283, en comptant à partir de la droite, vous obtenez cette séquence de nombres:

  3 * 1 =  3             3
  8 * 2 = 16 --> 1 + 6 = 7
  2 * 1 =  2             2
  7 * 2 = 14 --> 1 + 4 = 5
+ 3 * 1 =  3             3
=                       20

L’algorithme vous oblige à additionner les chiffres individuels du numéro d’origine et les chiffres individuels du produit de ces chiffres "tous les deux chiffres à partir de la droite".

Donc à partir de la droite, vous additionnez 3 + (1 + 6) + 2 + (1 + 4) + 3, ce qui vous donne 20.

Si le numéro avec lequel vous vous retrouvez se termine par un zéro, ce qui est le cas pour 20, le numéro est valide.

Maintenant, votre question laisse entendre que vous voulez savoir comment générer la somme de contrôle, c'est facile, procédez comme suit:

  1. Sélectionnez un zéro supplémentaire pour que votre numéro passe de xyxyxyxy à xyxyxyxy0
  2. Calculez la somme de contrôle luhn pour le nouveau numéro
  3. Prenez la somme, module 10, pour obtenir un seul chiffre compris entre 0 et 10
  4. Si le chiffre est 0, alors félicitations, votre chiffre de somme de contrôle était égal à zéro
  5. Sinon, calculez 10 chiffres pour obtenir ce dont vous avez besoin pour le dernier chiffre au lieu de ce zéro

Exemple: le nombre est 12345

  1. Pointage sur un zéro: 123450
  2. Calculez la somme de contrôle luhn pour 123450, ce qui donne

    0   5    4    3    2    1
    1   2    1    2    1    2  <-- factor
    0   10   4    6    2    2  <-- product
    0  1 0   4    6    2    2  <-- sum these to: 0+1+0+4+6+2+2=15
    
  3. Prenez la somme (15), module 10, qui vous donne 5

  4. Le chiffre (5) n'est pas zéro
  5. Calculez 10-5, ce qui vous donne 5, le dernier chiffre doit être 5.

Le résultat est donc 123455.

Autres conseils

votre php est buggy, il mène dans une boucle infinie. Ceci est la version de travail que j'utilise, modifiée à partir de votre code

  

fonction Luhn ($ number) {

$stack = 0;
$number = str_split(strrev($number));

foreach ($number as $key => $value)
{
    if ($key % 2 == 0)
    {
        $value = array_sum(str_split($value * 2));
    }
    $stack += $value;
}
$stack %= 10;

if ($stack != 0)
{
    $stack -= 10;     $stack = abs($stack);
}


$number = implode('', array_reverse($number));
$number = $number . strval($stack);

return $number; 
     

}

Créez un php et exécutez-le chez votre hôte local Luhn (xxxxxxxx) pour confirmer.

MAUVAIS

Je ne peux littéralement pas croire combien il y a de mises en œuvre minables.

  

IDAutomation possède un assemblage .NET avec une fonction MOD10 () pour créer mais cela ne semble tout simplement pas fonctionner. Dans Reflector, le code est beaucoup trop long pour ce qu’il est censé faire de toute façon.

MAUVAIS

Ce gâchis d'une page actuellement liée à partir de Wikipedia (!) For Javascript comporte plusieurs implémentations de vérification qui ne renvoient même pas la même valeur lorsque je les appelle.

BON

La page liée à la page Luhn de Wikipedia possède un encodeur Javascript qui semble fonctionner:

// Javascript
String.prototype.luhnGet = function()
{
    var luhnArr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]], sum = 0;
    this.replace(/\D+/g,"").replace(/[\d]/g, function(c, p, o){
        sum += luhnArr[ (o.length-p)&1 ][ parseInt(c,10) ]
    });
    return this + ((10 - sum%10)%10);
};

alert("54511187504546384725".luhnGet());​

BON

Cette page très utile EE4253 vérifie le chiffre de contrôle et affiche également le calcul complet et l'explication.

BON

J’avais besoin de code C # et j’ai fini par utiliser ceci code code du projet :

// C#
public static int GetMod10Digit(string data)
        {
            int sum = 0;
            bool odd = true;
            for (int i = data.Length - 1; i >= 0; i--)
            {
                if (odd == true)
                {
                    int tSum = Convert.ToInt32(data[i].ToString()) * 2;
                    if (tSum >= 10)
                    {
                        string tData = tSum.ToString();
                        tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
                    }
                    sum += tSum;
                }
                else
                    sum += Convert.ToInt32(data[i].ToString());
                odd = !odd;
            }

            int result = (((sum / 10) + 1) * 10) - sum;
            return result % 10;
        }

BON

Ce code de validation en C # semble fonctionner, s'il est un peu lourd. Je viens de l'utiliser pour vérifier si la réponse ci-dessus était correcte.

Il existe maintenant un dépôt Github basé sur la question / réponse originale. Voir

https://github.com/xi-project/xi-algorithm

Il est également disponible chez Packagist

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

function isLuhnValid($number)
{
    if (empty($number))
        return false;

    

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>j = 0;

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>base = str_split($number);

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>sum = array_pop(

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>base); while ((

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>actual = array_pop(

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>base)) !== null) { if (

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>j % 2 == 0) {

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>actual *= 2; if (

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>actual > 9)

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>actual -= 9; }

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>j++;

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>sum +=

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>actual; } return

C’est une fonction qui pourrait vous aider, elle est courte et fonctionne très bien.

<*>sum % 10 === 0; }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top