编写 Luhn 算法
Programming a Luhn Algorithm
我有一个 luhn 算法,我正在尝试按照维基百科上的算法步骤进行操作,并且它适用于他们提供的示例。我认为这是正确的。但它不适用于我的任何个人卡。也没有我在寻找解决方案时发现的任何测试值。
我已经看到使用 lamba 和内联 linq 的其他解决方案。但我不想复制和粘贴任何东西。我宁愿真正理解我在编码什么。
49927398716 pass
49927398717 fail
1234567812345678 fail
1234567812345670 pass (mine fails this one)
我的代码如下。
private bool CalculateLuhnAlgorithm()
{
string newListOfNumbers = this._number; //this._number is a string
int sumOfAllValues = 0;
if (_cardType != CardType.Unavailable)
{
//odd numbers minus the check Digit.
for (int i = this._number.Length - 2; i > 0; i -= 2)
{
int number = (int)char.GetNumericValue(this._number[i]) * 2;
if (number >= 10)
{
string concatinatedNumber = number.ToString();
int firstNumber = (int)char.GetNumericValue(concatinatedNumber[0]);
int secondNumber = (int)char.GetNumericValue(concatinatedNumber[1]);
number = firstNumber + secondNumber;
}
newListOfNumbers = newListOfNumbers.Remove(i, 1);
newListOfNumbers = newListOfNumbers.Insert(i, number.ToString());
}
// add up the complete total
foreach (char c in newListOfNumbers)
{
sumOfAllValues += (int)char.GetNumericValue(c);
}
}
// get the luhn validity
return (sumOfAllValues %10) == 0;
}
问题是您的 for
循环在 i > 0
期间继续。这意味着您永远不会将第一个数字加倍。它应该在 i >= 0
.
期间继续
下面是一些其他的建议。
当您将 number
加倍并且大于 10 时,您可以这样做
if(number > 10)
number = (number % 10) + 1;
这是有效的,因为最高的单个数字值 (9) 加倍是 (18)。所以第一个数字总是 1,你可以 mod 数字乘以 10 得到第二个数字。
您应该添加一个检查以确保该字符串具有偶数位数,并且可能具体的下限和上限取决于您使用的帐号是什么。
与其创建第二个包含 "odd" 数字加倍的字符串,不如在遍历数字时跟踪总和,如下所示。
private bool CalculateLuhnAlgorithm()
{
if(this.number.Length % 2 != 0)
return false; // Or maybe throw an exception?
if (_cardType != CardType.Unavailable)
{
int sumOfAllValues = 0;
//odd numbers minus the check Digit.
for (int i = 0; i < this._number.Length; i++)
{
if(i%2 != 0) // because i is 0 based instead of 1 based.
sumOfAllValues += (int)char.GetNumericValue(this._number[i])
else
{
int number = (int)char.GetNumericValue(this._number[i]) * 2;
if (number >= 10)
{
number = (number % 10) + 1;
}
sumOfAllValues += number;
}
}
// get the luhn validity
return (sumOfAllValues %10) == 0;
}
else
{
// Not completely sure what this should do,
// but in your code it just results in true.
return true;
}
}
最后,您可能希望将 char.GetNumericValue
替换为 int.TryParse
,以便验证包含非数字值的字符串。 char.GetNumericValue
returns -1 对于非数字值。
int digit = 0;
if(!int.TryParse(this._number.SubString(i, 1), out digit)
{
return false; // Or throw an exception.
}
我有一个 luhn 算法,我正在尝试按照维基百科上的算法步骤进行操作,并且它适用于他们提供的示例。我认为这是正确的。但它不适用于我的任何个人卡。也没有我在寻找解决方案时发现的任何测试值。
我已经看到使用 lamba 和内联 linq 的其他解决方案。但我不想复制和粘贴任何东西。我宁愿真正理解我在编码什么。
49927398716 pass
49927398717 fail
1234567812345678 fail
1234567812345670 pass (mine fails this one)
我的代码如下。
private bool CalculateLuhnAlgorithm()
{
string newListOfNumbers = this._number; //this._number is a string
int sumOfAllValues = 0;
if (_cardType != CardType.Unavailable)
{
//odd numbers minus the check Digit.
for (int i = this._number.Length - 2; i > 0; i -= 2)
{
int number = (int)char.GetNumericValue(this._number[i]) * 2;
if (number >= 10)
{
string concatinatedNumber = number.ToString();
int firstNumber = (int)char.GetNumericValue(concatinatedNumber[0]);
int secondNumber = (int)char.GetNumericValue(concatinatedNumber[1]);
number = firstNumber + secondNumber;
}
newListOfNumbers = newListOfNumbers.Remove(i, 1);
newListOfNumbers = newListOfNumbers.Insert(i, number.ToString());
}
// add up the complete total
foreach (char c in newListOfNumbers)
{
sumOfAllValues += (int)char.GetNumericValue(c);
}
}
// get the luhn validity
return (sumOfAllValues %10) == 0;
}
问题是您的 for
循环在 i > 0
期间继续。这意味着您永远不会将第一个数字加倍。它应该在 i >= 0
.
下面是一些其他的建议。
当您将 number
加倍并且大于 10 时,您可以这样做
if(number > 10)
number = (number % 10) + 1;
这是有效的,因为最高的单个数字值 (9) 加倍是 (18)。所以第一个数字总是 1,你可以 mod 数字乘以 10 得到第二个数字。
您应该添加一个检查以确保该字符串具有偶数位数,并且可能具体的下限和上限取决于您使用的帐号是什么。
与其创建第二个包含 "odd" 数字加倍的字符串,不如在遍历数字时跟踪总和,如下所示。
private bool CalculateLuhnAlgorithm()
{
if(this.number.Length % 2 != 0)
return false; // Or maybe throw an exception?
if (_cardType != CardType.Unavailable)
{
int sumOfAllValues = 0;
//odd numbers minus the check Digit.
for (int i = 0; i < this._number.Length; i++)
{
if(i%2 != 0) // because i is 0 based instead of 1 based.
sumOfAllValues += (int)char.GetNumericValue(this._number[i])
else
{
int number = (int)char.GetNumericValue(this._number[i]) * 2;
if (number >= 10)
{
number = (number % 10) + 1;
}
sumOfAllValues += number;
}
}
// get the luhn validity
return (sumOfAllValues %10) == 0;
}
else
{
// Not completely sure what this should do,
// but in your code it just results in true.
return true;
}
}
最后,您可能希望将 char.GetNumericValue
替换为 int.TryParse
,以便验证包含非数字值的字符串。 char.GetNumericValue
returns -1 对于非数字值。
int digit = 0;
if(!int.TryParse(this._number.SubString(i, 1), out digit)
{
return false; // Or throw an exception.
}