implementing luhn algorithm using c#

2019-02-07 14:58发布

I am using following code to implement Luhn algorithm for credit card check in c# language but could not get the output to generate the check sum its showing validity: kindly help me.Thank you in advance

public class Program
{
    private static void Main(string[]creditcard)
    {
        int sum = 0, d;
        string num ="7992739871";
        int a = 0;

        for (int i = num.Length - 2; i >= 0; i--)
        {
            d = Convert.ToInt32(num.Substring(i, 1));
            if (a % 2 == 0)
                d = d * 2;
            if (d > 9)
                d -= 9;
            sum += d;
            a++;
        }

        if ((10 - (sum % 10) == Convert.ToInt32(num.Substring(num.Length - 1))))
            Console.WriteLine("valid");

        Console.WriteLine("sum of digits of the number" + sum);
    }
}    

标签: c# checksum luhn
5条回答
一夜七次
2楼-- · 2019-02-07 15:44

Here are some extension methods that compute a Luhn checkdigit, validate a number with a checkdigit, and add a checkdigit to a number. Tested in .NET 4.5.

There are extension methods for strings, ints, int64s and IList.

I got some ideas for this from rosettacode.org

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

public static class CheckDigitExtension
{
    static readonly int[] Results = { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 };

    #region extension methods for IList<int>

    /// <summary>
    /// For a list of digits, compute the ending checkdigit 
    /// </summary>
    /// <param name="digits">The list of digits for which to compute the check digit</param>
    /// <returns>the check digit</returns>
    public static int CheckDigit(this IList<int> digits)
    {
        var i = 0;
        var lengthMod = digits.Count%2;
        return (digits.Sum(d => i++ % 2 == lengthMod ? d : Results[d]) * 9) % 10;
    }

    /// <summary>
    /// Return a list of digits including the checkdigit
    /// </summary>
    /// <param name="digits">The original list of digits</param>
    /// <returns>the new list of digits including checkdigit</returns>
    public static IList<int> AppendCheckDigit(this IList<int> digits)
    {
        var result = digits;
        result.Add(digits.CheckDigit());
        return result;
    }

    /// <summary>
    /// Returns true when a list of digits has a valid checkdigit
    /// </summary>
    /// <param name="digits">The list of digits to check</param>
    /// <returns>true/false depending on valid checkdigit</returns>
    public static bool HasValidCheckDigit(this IList<int> digits)
    {
        return digits.Last() == CheckDigit(digits.Take(digits.Count - 1).ToList());
    }

    #endregion extension methods for IList<int>

    #region extension methods for strings

    /// <summary>
    /// Internal conversion function to convert string into a list of ints
    /// </summary>
    /// <param name="digits">the original string</param>
    /// <returns>the list of ints</returns>
    private static IList<int> ToDigitList(this string digits)
    {
        return digits.Select(d => d - 48).ToList();
    }

    /// <summary>
    /// For a string of digits, compute the ending checkdigit 
    /// </summary>
    /// <param name="digits">The string of digits for which to compute the check digit</param>
    /// <returns>the check digit</returns>
    public static string CheckDigit(this string digits)
    {
        return digits.ToDigitList().CheckDigit().ToString(CultureInfo.InvariantCulture);
    }

    /// <summary>
    /// Return a string of digits including the checkdigit
    /// </summary>
    /// <param name="digits">The original string of digits</param>
    /// <returns>the new string of digits including checkdigit</returns>
    public static string AppendCheckDigit(this string digits)
    {
        return digits + digits.CheckDigit(); 
    }

    /// <summary>
    /// Returns true when a string of digits has a valid checkdigit
    /// </summary>
    /// <param name="digits">The string of digits to check</param>
    /// <returns>true/false depending on valid checkdigit</returns>
    public static bool HasValidCheckDigit(this string digits)
    {
        return digits.ToDigitList().HasValidCheckDigit();
    }

    #endregion extension methods for strings

    #region extension methods for integers

    /// <summary>
    /// Internal conversion function to convert int into a list of ints, one for each digit
    /// </summary>
    /// <param name="digits">the original int</param>
    /// <returns>the list of ints</returns>
    private static IList<int> ToDigitList(this int digits)
    {
        return digits.ToString(CultureInfo.InvariantCulture).Select(d => d - 48).ToList();
    }

    /// <summary>
    /// For an integer, compute the ending checkdigit 
    /// </summary>
    /// <param name="digits">The integer for which to compute the check digit</param>
    /// <returns>the check digit</returns>
    public static int CheckDigit(this int digits)
    {
        return digits.ToDigitList().CheckDigit();
    }

    /// <summary>
    /// Return an integer including the checkdigit
    /// </summary>
    /// <param name="digits">The original integer</param>
    /// <returns>the new integer including checkdigit</returns>
    public static int AppendCheckDigit(this int digits)
    {
        return digits * 10 + digits.CheckDigit();
    }

    /// <summary>
    /// Returns true when an integer has a valid checkdigit
    /// </summary>
    /// <param name="digits">The integer to check</param>
    /// <returns>true/false depending on valid checkdigit</returns>
    public static bool HasValidCheckDigit(this int digits)
    {
        return digits.ToDigitList().HasValidCheckDigit();
    }

    #endregion extension methods for integers

    #region extension methods for int64s

    /// <summary>
    /// Internal conversion function to convert int into a list of ints, one for each digit
    /// </summary>
    /// <param name="digits">the original int</param>
    /// <returns>the list of ints</returns>
    private static IList<int> ToDigitList(this Int64 digits)
    {
        return digits.ToString(CultureInfo.InvariantCulture).Select(d => d - 48).ToList();
    }

    /// <summary>
    /// For an integer, compute the ending checkdigit 
    /// </summary>
    /// <param name="digits">The integer for which to compute the check digit</param>
    /// <returns>the check digit</returns>
    public static int CheckDigit(this Int64 digits)
    {
        return digits.ToDigitList().CheckDigit();
    }

    /// <summary>
    /// Return an integer including the checkdigit
    /// </summary>
    /// <param name="digits">The original integer</param>
    /// <returns>the new integer including checkdigit</returns>
    public static Int64 AppendCheckDigit(this Int64 digits)
    {
        return digits * 10 + digits.CheckDigit();
    }

    /// <summary>
    /// Returns true when an integer has a valid checkdigit
    /// </summary>
    /// <param name="digits">The integer to check</param>
    /// <returns>true/false depending on valid checkdigit</returns>
    public static bool HasValidCheckDigit(this Int64 digits)
    {
        return digits.ToDigitList().HasValidCheckDigit();
    }

    #endregion extension methods for int64s
}

Here are some XUnit test cases that show how the extension methods work.

public class CheckDigitExtensionShould
{
    [Fact]
    public void ComputeCheckDigits()
    {
        Assert.Equal(0, (new List<int> { 0 }).CheckDigit());
        Assert.Equal(8, (new List<int> { 1 }).CheckDigit());
        Assert.Equal(6, (new List<int> { 2 }).CheckDigit());

        Assert.Equal(0, (new List<int> { 3, 6, 1, 5, 5 }).CheckDigit());
        Assert.Equal(0, 36155.CheckDigit());
        Assert.Equal(8, (new List<int> { 3, 6, 1, 5, 6 }).CheckDigit());
        Assert.Equal(8, 36156.CheckDigit());
        Assert.Equal(6, 36157.CheckDigit());
        Assert.Equal("6", "36157".CheckDigit());
        Assert.Equal("3", "7992739871".CheckDigit());
    }

    [Fact]
    public void ValidateCheckDigits()
    {
        Assert.True((new List<int> { 3, 6, 1, 5, 6, 8 }).HasValidCheckDigit());
        Assert.True(361568.HasValidCheckDigit());
        Assert.True("361568".HasValidCheckDigit());
        Assert.True("79927398713".HasValidCheckDigit());
    }

    [Fact]
    public void AppendCheckDigits()
    {
        Console.WriteLine("36156".CheckDigit());
        Console.WriteLine("36156".AppendCheckDigit());
        Assert.Equal("361568", "36156".AppendCheckDigit());
        Assert.Equal("79927398713", "7992739871".AppendCheckDigit());
    }
}
查看更多
太酷不给撩
3楼-- · 2019-02-07 15:47

Compact Luhn check:

public static bool Luhn(string digits)
{
    return digits.All(char.IsDigit) && digits.Reverse()
        .Select(c => c - 48)
        .Select((thisNum, i) => i % 2 == 0
            ? thisNum
            :((thisNum *= 2) > 9 ? thisNum - 9 : thisNum)
        ).Sum() % 10 == 0;
}

Fiddle: https://dotnetfiddle.net/CCwE48

查看更多
Lonely孤独者°
4楼-- · 2019-02-07 15:48

This one will do it I believe:

static void Main(string[] args)
    {
        string number = "1762483";
        int digit = 0;
        int sum = 0;

        for (int i = 0; i <= number.Length - 1; i++)
        {

            if (i % 2 == 1)
            {
                digit = int.Parse(number.Substring(i, 1));
                sum += DoubleDigitValue(digit);

                Console.WriteLine(digit);
            }
            else
            {
                digit = int.Parse(number.Substring(i, 1));
                sum += digit;
            }

        }
        Console.WriteLine(sum);
        if (sum % 10 == 0)
        {
            Console.WriteLine("valid");
        }
        else
        {
            Console.WriteLine("Invalid");
        }
    }
    static int DoubleDigitValue(int digit)
    {
        int sum;
        int doubledDigit = digit * 2; 
        if (doubledDigit >= 10)
        {
            sum = 1 + doubledDigit % 10;
        } else
        {
            sum = doubledDigit; 
        }
        return sum; 
    }
查看更多
虎瘦雄心在
5楼-- · 2019-02-07 15:51

Your algorithm is correct, but you're testing it wrong way.

I can see your sample input is from wiki page: Luhn algorithm. Difference is, they are calculating check digit for "7992739871X", where X is the check digit they're looking for. Your code validates number your already have!

Change your input to "79927398713" and it will mark it as correct number.

Update

OK, I see where is the problem. You're not taking this part of algorithm right:

From the rightmost digit, which is the check digit, moving left, double the value of every second digit;

Your code takes every other digit, but not necessary starting from most left digit. Try this code:

for (int i = 0; i < num.Length; i++)
{
    d = Convert.ToInt32(num.Substring(num.Length - 1 - i, 1));
    if (a % 2 == 0)
        d = d * 2;
    if (d > 9)
        d -= 9;
    sum += d;
    a++;
}

var checkDigit = 10 - (sum % 10);
查看更多
Evening l夕情丶
6楼-- · 2019-02-07 15:53

You can do it very simply (reference),

    public static bool Mod10Check(string creditCardNumber)
    {              
        // check whether input string is null or empty
        if (string.IsNullOrEmpty(creditCardNumber))
        {
            return false;
        }

        int sumOfDigits = creditCardNumber.Where((e) => e >= '0' && e <= '9')
                        .Reverse()
                        .Select((e, i) => ((int)e - 48) * (i % 2 == 0 ? 1 : 2))
                        .Sum((e) => e / 10 + e % 10);


        return sumOfDigits % 10 == 0;
    }
查看更多
登录 后发表回答