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 :

Modulo 10 Récursif


Sujet :

C#

  1. #1
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut Modulo 10 Récursif
    bonjour à tous, dans mes anciens posts vous comprendrez pourquoi je parles de bulletin de versement.

    Je ne comprends pas trop le modulo 10 récursif des bulletins de versement ... c'est un algo trop compliqué je trouve.. si quelqu'un peut m'aider à décortiquer ça en plus simple...

    voici la doc de la poste https://www.postfinance.ch/content/d...scr_man_fr.pdf

    Merci d'avance !

  2. #2
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Suppression de couleur d'une image (ton dernier post)!
    Quel est le rapport???
    Et surtout quelle est ta question?? Parce que je ne pense pas que traiter la doc à ta place en sois une

  3. #3
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Tu n'as pas besoin du modulo 10 pour ton problème.
    Tu vérifies via une regex ou autre que le champ correspond au format attention (un certain nombre de chiffres, une virgule, deux chiffres) ou tu utilises Double.TryParse.

  4. #4
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut
    la question n'est pas vraiment de lire la doc à ma place, c'est à la page 5 qu'il faut jeter un coup d'oeil... car je ne comprends pas trop leur système de modulo ... la question est si quelqu'un peu m'expliquer ça d'une façon beaucoup plus simplifié soit de me donner un code c# qui traînerait...

  5. #5
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Il suffit de créer un tableau multidimensionnel (10 lignes, 10 colonnes)
    Dans ton code postal tu as 10 caractères (70-004152-? les 00 après - seront à rajouter);
    Le ? est a deviné, pour cela l'exemple qui t'est fournis est plutôt explicite:
    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
    int[,] tableau = { { 0, 9, 4, 6, 8, 2, 7, 1, 3, 5 }, { 9, 4, 6, 8, 2, 7, 1, 3, 5, 0 }, { 4, 6, 8, 2, 7, 1, 3, 5, 0, 9 }, {6, 8, 2, 7, 1, 3, 5, 0, 9, 4} {...}};
    System.Text.StringBuilder codePostal = new System.Text.StringBuilder();
    codePostal.Append("70-004152-?");
    int i=0;
    int h=0;
    while(codePostal[10].ToString()=="?"){
                    if (h == 10)
                    {
                        int cleProduit = 10 - i;
                        codePostal.Remove(10, 1);
                        codePostal.Append(cleProduit.ToString());
                    }
                    else
                    {
                        if (codePostal[h].ToString()!="-")
                            i = tableau[i, int.Parse(codePostal[h].ToString())];
                    }
                    h++;
    }
    Je ne suis pas sur du bon fonctionnement, mais cela devrait t'aider à résoudre ton problème si j'ai bien compris... Ainsi tu aura ta clé produit

  6. #6
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Au temps pour moi, j'avais mal saisi le problème (ou le lient a t-il été ajouté plus tard) ?

    Version complète (padding inclus) un peu plus "propre" (question de préférence) :
    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
    private IEnumerable<int> GetDigitsForCheckSum(string str)
    {
        int lowerBound = 2;
        int upperBound = str.LastIndexOf('-');
        int padLength = 7 - (upperBound - lowerBound);
     
        for(int i = 0; i < lowerBound; i++) yield return (int)(str[i] - '0');
        for(int i = 0; i < padLength; i++) yield return 0;
        for(int i = lowerBound + 1; i < upperBound; i++) yield return (int)(str[i] - '0');
        yield return (int)(str[upperBound + 1] - '0');
    }
     
     
    private bool IsChecksumCorrect(string str)
    {
        int[] reports = { 0, 9, 4, 6, 8, 2, 7, 1, 3, 5 };
        int report = 0;
        int count = 0;
     
        foreach(int digit in GetDigitsForCheckSum(str))
        {
            if (count == 8) return digit == 10 - report;
            report = reports[(digit + 10 - report) % 10];
            ++count;
        }
        return false;
    }
    EDIT : Le code que j'avais écrit me dérangeait, j'y suis revenu pour en faire une version plus explicite.

  7. #7
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut
    salut FrameBreak, alors je t'explique, j'ai déjà le numéro de compte (que je récupère grâce à un OCR) mais justement il faut que je vérifie s'il est correct...


    DonQuiche, merci encore et encore de ton aide et soutien,
    Mais j'ai un peu de peine à comprendre ton code ...

  8. #8
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Citation Envoyé par lilmemt Voir le message
    salut FrameBreak, alors je t'explique, j'ai déjà le numéro de compte (que je récupère grâce à un OCR) mais justement il faut que je vérifie s'il est correct...
    Dans ce cas la il te reste juste à comparer la clef produit (qui validera le numéro de compte) si j'ai bien compris...

  9. #9
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut
    Parce que je lis une image et je récupère la suite de nombre qui se trouve tout en bas, et c'est par rapport à ça que je vais faire mon CheckSum ... d'abord par rapport au montant, donc la première suite avant le '>' puis le numéro de référence entre le '>' et le '+' puis le numéro de compte qui est tout à la fin ...

    avec le code que vous m'avez fourni je pensais faire ainsi :
    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
    32
    33
    34
     public void CheckSum()
            {
                int[,] tableau = { 
                                 { 0, 9, 4, 6, 8, 2, 7, 1, 3, 5 }, 
                                 { 9, 4, 6, 8, 2, 7, 1, 3, 5, 0 }, 
                                 { 4, 6, 8, 2, 7, 1, 3, 5, 0, 9 }, 
                                 { 6, 8, 2, 7, 1, 3, 5, 0, 9, 4 },
                                 { 8, 2, 7, 1, 3, 5, 0, 9, 4, 6 },
                                 { 2, 7, 1, 3, 5, 0, 9, 4, 6, 8 },
                                 { 7, 1, 3, 5, 0, 9, 4, 6, 8, 2 },
                                 { 1, 3, 5, 0, 9, 4, 6, 8, 2, 7 },
                                 { 3, 5, 0, 9, 4, 6, 8, 2, 7, 1 },
                                 { 5, 0, 9, 4, 6, 8, 2, 7, 1, 3 } 
                                 };
                System.Text.StringBuilder codePostal = new System.Text.StringBuilder();
                codePostal.Append(strCompte);           //strCompte contient le num de compte récupéré plus tôt..
                int i = 0;
                int h = 0;
                while (codePostal[10].ToString() == "?")
                {
                    if (h == 10)
                    {
                        int cleProduit = 10 - i;
                        codePostal.Remove(10, 1);
                        codePostal.Append(cleProduit.ToString());
                    }
                    else
                    {
                        if (codePostal[h].ToString() != "-")
                            i = tableau[i, int.Parse(codePostal[h].ToString())];
                    }
                    h++;
                }
            }
    mais un truc qui me dérange, c'est le int i, à aucun moment il change, s'incrémente ou autre ...

    Dîtes moi si ce code jouerais s'il vous plaît ...

  10. #10
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    L'entier i ne s'incrémente pas:
    - il prend les valeurs retourner par le tableau, permettant ainsi à connaitre la prochaine ligne du tableau
    - Une fois la prochaine ligne connue, la boucle incrémente h qui se déplace dans le codepostal prenant le chiffre suivant.
    - Lors du prochain passage dans le tableau, nous avons la ligne i et la colonne h, ces 2 permettrons de connaitre la ligne suivante.
    Et ainsi de suite...

    Est-ce que cela répond à ta question??

  11. #11
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut
    Oui cela réponds très clairement à ma question

    Merci beaucoup FrameBreak !!

  12. #12
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Le code que j'ai proposé est assez simple à comprendre en fait :
    * La première fonction retourne, pour une chaîne "01-1564-5" une énumération d'enters 0, 1, 0, 0, 1, 5, 6, 4, 5. Autrement dit elle assure le parsing et le padding.
    * La seconde fonction est le coeur de l'algorithme : en effet, en regardant le tableau, il est assez facile de voir que d'une ligne à l'autre on décale d'un cran vers la gauche à chaque fois. Autrement dit, c'est comme si le numéro de la colonne ("digit") était soustrait de "report", modulo 10. Puis on interroge le tableau avec cette valeur corrigée pour obtenir le nouveau "report". Quant au chiffre clé final, c'est simplement 10 - report.

  13. #13
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut
    DonQuiche, donc si je veux "adapter" ton code au mien, j'ai juste à changer la ligne du int upperBound ... Je vais essayer ça aussi comme ça y'a pas de jaloux

    Merci encore à vous deux je vous redonnes des nouvelles très vite si ça marche bien ou pas.

    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
    private IEnumerable<int> GetDigitsForCheckSum(string str)
    {
        int lowerBound = 2;
        int upperBound = str.Length;
        int padLength = 7 - (upperBound - lowerBound);
     
        for(int i = 0; i < lowerBound; i++) yield return (int)(str[i] - '0');
        for(int i = 0; i < padLength; i++) yield return 0;
        for(int i = lowerBound + 1; i < upperBound; i++) yield return (int)(str[i] - '0');
        yield return (int)(str[upperBound + 1] - '0');
    }
     
     
    private bool IsChecksumCorrect(string str)
    {
        int[] reports = { 0, 9, 4, 6, 8, 2, 7, 1, 3, 5 };
        int report = 0;
        int count = 0;
     
        foreach(int digit in GetDigitsForCheckSum(str))
        {
            if (count == 8) return digit == 10 - report;
            report = reports[(digit + 10 - report) % 10];
            ++count;
        }
        return false;
    }

  14. #14
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut
    DonQuiche, en testant ton code, je me suis rendu compte, que à aucun moment il retourne "true"... Comment je peux savoir si c'est juste ou pas alors ... ?

  15. #15
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par lilmemt Voir le message
    DonQuiche, donc si je veux "adapter" ton code au mien, j'ai juste à changer la ligne du int upperBound ...
    Non puisque sur tes bulletins le numéro de compte inclut déjà la somme de contrôle. Le but est bien de vérifier que le numéro est correct, pas de calculer une somme de contrôle ?

    Si tu voulais cette dernière option, il faudrait changer upperBound et modifier la ligne du return dans la seconde fonction.

  16. #16
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut
    Oui c'est bien cela, car le chiffre clé on l'a déjà (dernier caractère) donc il suffit de contrôler si le numéro de compte est correct, puis je devrais faire pareil avec le montant et le num de réf normalement...

    Mais le numéro de compte quand je le récupère sur la dernière ligne il est sous cette forme "010001628" ...

  17. #17
    Membre éclairé
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2011
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2011
    Messages : 610
    Points : 713
    Points
    713
    Par défaut
    Citation Envoyé par lilmemt Voir le message
    Mais le numéro de compte quand je le récupère sur la dernière ligne il est sous cette forme "010001628" ...
    Ce qui est correct et devrait correspondre au code 01-000162-8 entrant non??

  18. #18
    Nouveau membre du Club
    Inscrit en
    Novembre 2009
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 59
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par FrameBreak Voir le message
    Ce qui est correct et devrait correspondre au code 01-000162-8 entrant non??
    Oui mais non ... Ce serait ce genre si je récupérais la ligne ou le numéro est écrit "01-162-8" mais moi je récupère tout en bas, le numéro "préimprimé" ... le numéro de compte se trouve tout à la fin... et moi je découpe avec des Regex.Split cette dernière ligne .. donc je récupère "010001628"

  19. #19
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Ah oui, en bas à droite, effectivement. Et bien c'est encore plus simple alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    private bool IsChecksumCorrect(string str)
    {
        int[] reports = { 0, 9, 4, 6, 8, 2, 7, 1, 3, 5 };
        int report = 0;
     
        for(int i = 0; i < 8; i++)
        {
            int digit = str[i] - '0';
            report = reports[(digit + 10 - report) % 10];
        }
     
        int lastDigit = str[8] - '0';
        return lastDigit == 10 - report;
    }

Discussions similaires

  1. [débutant]Syntaxe modulo
    Par Regis.C dans le forum Langage
    Réponses: 3
    Dernier message: 29/08/2007, 09h17
  2. XPATH XSL Récursif (très débutant!)
    Par luta dans le forum XSL/XSLT/XPATH
    Réponses: 14
    Dernier message: 24/08/2004, 10h04
  3. idFTP.DirectoryListing récursif + TreeNode
    Par fredfred dans le forum Composants VCL
    Réponses: 3
    Dernier message: 05/07/2004, 15h53
  4. Division entière et Modulo
    Par kase74 dans le forum SQL
    Réponses: 6
    Dernier message: 01/04/2004, 11h46
  5. Modulo en Assembleur
    Par SteelBox dans le forum Assembleur
    Réponses: 10
    Dernier message: 07/04/2003, 22h49

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