using System; using Developpez.Dotnet.Properties; namespace Developpez.Dotnet.Algorithms { /// /// Type de vérification par l'algorithme de Luhn. /// public enum LuhnCheckType { /// /// Aucun. /// None = 0, /// /// Carte de crédit. /// CreditCard = 1, /// /// Siren. /// Siren = 2, /// /// Siret. /// Siret = 3 } /// /// Algorithme de Luhn. /// /// L'algorithme de Luhn est décrit ici : /// http://en.wikipedia.org/wiki/Luhn_algorithm. /// public static class Luhn { /// /// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné. /// /// Nombre à vérifier. /// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon. public static bool Check(long number) { return Luhn.Check(number.ToString(), -1); } /// /// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné. /// /// Nombre à vérifier. /// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon. public static bool Check(string number) { return Luhn.Check(number, -1); } /// /// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné. /// /// Nombre à vérifier. /// Longueur de la chaîne. /// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon. private static bool Check(string number, int length) { #region Exceptions // La chaîne ne doit pas être vide : if (string.IsNullOrEmpty(number)) throw new ArgumentNullException(ExceptionMessages.StringNullOrEmpty); // La chaîne doit être de la longueur donnée : if (length > -1 && number.Length != length) throw new ArgumentException(string.Format(ExceptionMessages.StringWrongLength, length)); // La chaîne doit être un nombre : long result = 0; if (!long.TryParse(number, out result)) throw new ArgumentException(ExceptionMessages.StringNotANumber); // Le nombre doit être supérieur à zéro : if (result <= 0) throw new ArgumentOutOfRangeException( "number", string.Format(ExceptionMessages.NumberMustBeStrictlyPositive, "number")); #endregion int numberLength = number.Length; int figure = 0; int total = 0; int position = 1; for (int i = numberLength; i > 0; i--) { // Récupérer le chiffre en position courante : figure = int.Parse(number[i - 1].ToString()); // Multiplier ce chiffre par 2 ou 1 en fonction de sa position : figure = figure * ((position % 2 == 0) ? 2 : 1); // Retirer 9 si le résultat obtenu est > 10 // (équivaut à ajouter le chiffre des dizaines et celui des unités) : figure = (figure >= 10) ? figure - 9 : figure; total += figure; position++; } // Le chiffre valide pour la formule de Luhn, s'il est congru au modulo 10 : return (total % 10 == 0); } /// /// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné. /// /// Nombre à vérifier. /// Type de vérification. /// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon. public static bool Check(long number, LuhnCheckType checkType) { return Luhn.Check(number.ToString(), checkType); } /// /// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné. /// /// Nombre à vérifier. /// Type de vérification. /// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon. public static bool Check(string number, LuhnCheckType checkType) { switch (checkType) { case LuhnCheckType.CreditCard: return Luhn.Check(number, 16); case LuhnCheckType.Siren: return Luhn.Check(number, 9); case LuhnCheckType.Siret: return Luhn.Check(number, 14); case LuhnCheckType.None: default: return Luhn.Check(number, -1); } } } }