我使用下面的代码来实现Luhn算法用于c#语言的信用卡检查但是无法获得输出以生成其显示有效性的校验和:请帮助我.提前谢谢
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);
}
}
Run Code Online (Sandbox Code Playgroud)
daj*_*ajo 25
以下是一些扩展方法,用于计算Luhn checkdigit,使用checkdigit验证数字,以及向数字添加checkdigit.在.NET 4.5中测试过.
有字符串,整数,int64和IList的扩展方法.
我从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
}
Run Code Online (Sandbox Code Playgroud)
以下是一些XUnit测试用例,展示了扩展方法的工作原理.
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());
}
}
Run Code Online (Sandbox Code Playgroud)
gar*_*ryp 16
紧凑型Luhn检查:
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;
}
Run Code Online (Sandbox Code Playgroud)
小提琴:https://dotnetfiddle.net/CCwE48
这是一个正确且快速的实现:
bool PassesLuhnCheck(string value)
{
long sum = 0;
for (int i = 0; i < value.Length; i++)
{
var digit = value[value.Length - 1 - i] - '0';
sum += (i % 2 != 0) ? GetDouble(digit) : digit;
}
return sum % 10 == 0;
int GetDouble(long i)
{
switch (i)
{
case 0: return 0;
case 1: return 2;
case 2: return 4;
case 3: return 6;
case 4: return 8;
case 5: return 1;
case 6: return 3;
case 7: return 5;
case 8: return 7;
case 9: return 9;
default: return 0;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*zek -2
你的算法是正确的,但你测试它的方式是错误的。
我可以看到您的示例输入来自维基页面:Luhn 算法。不同的是,他们正在计算 的校验位"7992739871X",X他们正在寻找的校验位在哪里。您的代码验证了您已有的号码!
将您的输入更改为"79927398713",它会将其标记为正确的数字。
更新
好的,我明白问题出在哪里了。您没有正确理解这部分算法:
从最右边的数字(即校验位)开始,向左移动,每隔两个数字的值加倍;
您的代码每隔一个数字,但不一定从最左边的数字开始。试试这个代码:
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);
Run Code Online (Sandbox Code Playgroud)