2015-01-08 2 views
0

У меня есть алгоритм luhn, я пытаюсь выполнить шаги в Википедии для алгоритма, и он работает на примерах, которые они дают. и я подумал, что это правильно. Но это не работает ни на одной из моих личных карточек. ни на какие-либо из тестовых значений, которые я нашел в поисках решения этого.Программирование алгоритма Luhn

Я видел другие решения для этого, используя lamba и inline 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; 
    } 
+1

В чем ваш вопрос? – Adam

+1

Вы когда-нибудь обращались к последней цифре во входной строке? – DrKoch

+0

@DrKoch Контрольная цифра суммируется с другими числами, которые должны приводить к делению на 10. – juharr

ответ

2

Проблема заключается в том, что ваш for цикл продолжается, пока i > 0. Это означает, что вы никогда не удваиваете первую цифру. Вместо этого он должен продолжаться, пока i >= 0.

Теперь вот несколько других предложений.

Когда вы дважды number и это больше, чем 10, вы можете просто сделать

if(number > 10) 
    number = (number % 10) + 1; 

Это работает, потому что самое высокое одно значение цифры (9) два раза в (18). Итак, первая цифра всегда 1, и вы можете просто изменить число на 10, чтобы получить вторую цифру.

Вы должны добавить чек, чтобы убедиться, что строка имеет четное количество цифр и, возможно, конкретные нижние и верхние пределы в зависимости от того, с какими номерами счетов вы работаете.

Вместо того, чтобы создавать вторую строку, содержащую цифры с «нечетными», удваивать, вы должны просто отслеживать сумму при повторении по цифрам.

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; 
    } 
} 

Finially вы можете заменить char.GetNumericValue с int.TryParse так что вы можете проверить строки, содержащие не-числовые значения. char.GetNumericValue возвращает -1 для значений, которые не являются числовыми.

int digit = 0; 
if(!int.TryParse(this._number.SubString(i, 1), out digit) 
{ 
    return false; // Or throw an exception. 
}