一尘不染

如何实现Luhn算法?

algorithm

我正在尝试创建一个程序来验证基于luhn算法的10到12位数字长序列,但是我的程序不断告诉我,每个数字都是无效的,即使不是无效的。

这个数字应该是有效的,但是我的代码却不这样认为: 8112189876

该编号无效,我的程序同意此编号,因为它认为每个编号都无效: 8112189875

这是我的代码:

static void luhn(){
    System.out.print("Enter number to validate:\n");
    String pnr = input.nextLine();
    int length = pnr.length();
    int sum = 0;
    for (int i = 1, pos = length - 1; i < 10; i++, pos--){
        char tmp = pnr.charAt(pos);
        int num = tmp - 0
        int product;
        if (i % 2 != 0){
            product = num * 1;
        }
        else{
            product = num * 2;
        }
        if (product > 9)
            product -= 9;
        sum+= product;              
        boolean valid = (sum % 10 == 0);
        if (valid){
            System.out.print("Valid!\r");
        }
        else{
            System.out.print("Invalid!");
        }
    }
}

阅读 338

收藏
2020-07-28

共1个答案

一尘不染

我看到的第一件事是您拥有:

int num = tmp - 0

您应该改为:

int num = tmp - '0';

其次,您应该在循环 验证和for,因为您只关心处理完所有数字后的和。

第三,您从数字的末尾开始,并且不包括字符串的第一个数字。为什么不同时使用i这两个任务?

结果(工作)方法:

static void luhn(){
  System.out.print("Enter number to validate:\n");
  String pnr = input.nextLine();
  // this only works if you are certain all input will be at least 10 characters
  int extraChars = pnr.length() - 10;
  if (extraChars < 0) {
    throw new IllegalArgumentException("Number length must be at least 10 characters!");
  }
  pnr = pnr.substring(extraChars, 10 + extraChars);
  int sum = 0;
  // #3: removed pos
  for (int i = 0; i < pnr.length(); i++){
    char tmp = pnr.charAt(i);
    // #1: fixed the '0' problem
    int num = tmp - '0';
    int product;
    if (i % 2 != 0){
      product = num * 1;
    }
    else{
      product = num * 2;
    }
    if (product > 9)
      product -= 9;
    sum+= product;              
  }
  // #2: moved check outside for loop
  boolean valid = (sum % 10 == 0);
  if (valid){
    System.out.print("Valid!\r");
  }
  else{
    System.out.print("Invalid!");
  }
}

从风格上讲 ,如果代替方法签名,则此方法会更有用

static void luhn() {

相反,它具有方法签名

static boolean luhn(String input) {

这很容易让您的代码String从任何来源(文件,硬编码等)获取,并对结果做任何事情(像打印消息一样打印消息,或执行其他操作)。很明显,你会移动System.out.printinput.nextLine()以及if(valid)这种方法的代码之外的位。

完整的重构程序:

import java.util.Scanner;

public class Luhn {
  private static Scanner input;

  public static void main(String... args) {
    input = new Scanner(System.in);
    System.out.print("Enter number to validate:\n");
    String pnr = input.nextLine();
    boolean result = luhn(pnr);
    printMessage(result);
    input.close();
  }

  static boolean luhn(String pnr){
    // this only works if you are certain all input will be at least 10 characters
    int extraChars = pnr.length() - 10;
    if (extraChars < 0) {
      throw new IllegalArgumentException("Number length must be at least 10 characters!");
    }
    pnr = pnr.substring(extraChars, 10 + extraChars);
    int sum = 0;
    for (int i = 0; i < pnr.length(); i++){
      char tmp = pnr.charAt(i);
      int num = tmp - '0';
      int product;
      if (i % 2 != 0){
        product = num * 1;
      }
      else{
        product = num * 2;
      }
      if (product > 9)
        product -= 9;
      sum+= product;              
    }
    return (sum % 10 == 0);
  }

  private static void printMessage(boolean valid) {
    if (valid){
      System.out.print("Valid!\r");
    }
    else{
      System.out.print("Invalid!");
    }
  }
}
2020-07-28