0

MySQL データベースには、正しい luhn 番号と正しくない luhn 番号 (luhn アルゴリズムを使用して検証されない番号) のレコードがあります。

間違った番号が 1 桁の入力ミスによるものであると仮定すると、可能な正しい番号のリストを取得したいと思います。目標は、このリストで可能な正しいレコードをフィルタリングしてから、別の基準で再度フィルタリングすることです。

[編集] 私自身の質問に答えて、有効な luhn 番号と 1 桁の入力ミス (luhn_typo(invalid, valid)) または 2 桁の交換 (luhn_swap(invalid, valid)) の結果として生じる無効な luhn 番号を比較する手順を次に示します。 )。

CREATE DEFINER=`root`@`localhost` FUNCTION `luhn_sum`(p_number VARCHAR(32)) RETURNS INT(11)
SQL SECURITY INVOKER
BEGIN
    DECLARE i, mysum, r, weight INT;

    SET weight = 1;
    SET mysum = 0;
    SET i = length(p_number);

    WHILE i > 0 DO
        SET r = substring(p_number, i, 1) * weight;
        SET mysum = mysum + IF(r > 9, r - 9, r);
        SET i = i - 1;
        SET weight = 3 - weight;
    END WHILE;

    RETURN mysum;
END;

CREATE DEFINER=`root`@`localhost` FUNCTION `luhn_typo`(p_number VARCHAR(32), t_number VARCHAR(32)) RETURNS TINYINT(1)
SQL SECURITY INVOKER
BEGIN
DECLARE r, val, new_val, len, str_len, weight,digit,new_digit INT;
DECLARE new_luhn VARCHAR(255);

  IF (p_number = t_number) THEN
      RETURN FALSE;
  END IF;

  SET r = luhn_sum(p_number) % 10;

  IF (r = 0) THEN
      RETURN FALSE;
  END IF;

  SET str_len = LENGTH(p_number);
  SET len = str_len;
  SET weight = 1;

  WHILE len > 0 DO
      SET digit = CAST(SUBSTRING(p_number, len, 1) AS SIGNED) * weight;
      SET val = IF(digit > 9, digit - 9, digit);

      SET new_val = IF(val < r, val - r + 10, val - r);
      SET new_digit = (IF(weight = 2 AND (new_val % 2 = 1), new_val + 9, new_val)) / weight;

      SET new_luhn = CONCAT(SUBSTRING(p_number, 1, len - 1), new_digit, SUBSTRING(p_number, len + 1, str_len - len));

      IF (new_luhn = t_number ) THEN
          RETURN TRUE;
      END IF;

      SET weight = 3 - weight;
      SET len = len - 1;
  END WHILE;

  RETURN  FALSE;
END;

CREATE DEFINER=`root`@`localhost` FUNCTION `luhn_swap`(p_number VARCHAR(32), t_number VARCHAR(32)) RETURNS VARCHAR(32) CHARSET latin1
  SQL SECURITY INVOKER
BEGIN
  DECLARE parity, r, pair_sum_delta, len INT;
  DECLARE digit_pair, str_len VARCHAR(2);

  IF (p_number = t_number) THEN
      RETURN FALSE;
  END IF;

  SET r = luhn_sum(p_number) % 10;

  IF (r = 0) THEN
      RETURN FALSE;
  END IF;

  SET str_len = LENGTH(p_number);
  SET len = str_len;
  SET parity = 1; -- odd

  WHILE len > 1 DO
      SET digit_pair = SUBSTRING(p_number, len - 1, 2);
      SET pair_sum_delta = (-luhn_sum(digit_pair) + luhn_sum(REVERSE(digit_pair))) * parity;

      IF ((r + pair_sum_delta) % 10 = 0) AND (t_number = CONCAT(SUBSTRING(p_number, 1, len -2), REVERSE(digit_pair), SUBSTRING(p_number, len + 1, str_len - len))) THEN
            RETURN TRUE;
      END IF;

      SET parity = -parity;
      SET len = len -1;    
  END WHILE;

  RETURN FALSE;
END;
4

0 に答える 0