【问题标题】:Credit card checker with Luhn algorith javascript带有 Luhn 算法 javascript 的信用卡检查器
【发布时间】:2021-12-11 11:13:37
【问题描述】:

我目前正在使用 Luhn 算法研究 codeacademy 的“信用卡检查器”,但是我的代码在有效数组上返回 false(应该返回)。你能帮我解决这个问题吗?

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];


// Add your functions below:

const validateCred = arr => {
  let totalSum = 0;
  let revList = arr.reverse();
  for (let i = 0; i < revList.length; i++) {
    let calcAmount = revList[i];
    if (i !== 0 && i%2 === 0) {
      calcAmount = revList[i] * 2;
      if (calcAmount > 9 ) {
        calcAmount -= 9;
        totalSum += calcAmount;
      } else {
        totalSum += calcAmount;
      }
    } else {
      totalSum += revList[i];
    }
  }
  return (totalSum%10 === 0 ? true : false);
};

console.log(validateCred(valid3))
console.log(validateCred(valid4))
console.log(validateCred(valid5))

【问题讨论】:

  • 我在运行你的代码时看到一个错误,返回语句中的sum 应该是totalSum吗?
  • sum 中的 return(sum%10 ... 是什么?它没有在您的代码中定义。
  • 它认为 Sum 变量有问题。它在循环之外并且也不正确
  • 我已经修复了,但还是没有解决问题

标签: javascript luhn


【解决方案1】:

一个简单的错误,检查if (i%2 === 1) {,算法需要每隔一个元素乘以2

arr.reverse() 也是个坏主意,改变了原来的数组。

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];


// Add your functions below:

const validateCred = arr => {
  let totalSum = 0;
  let revList = arr.reverse();
  for (let i = 0; i < revList.length; i++) {
    let calcAmount = revList[i];
    if (i%2 === 1) {
      calcAmount = revList[i] * 2;
      if (calcAmount > 9 ) {
        calcAmount -= 9;
        totalSum += calcAmount;
      } else {
        totalSum += calcAmount;
      }
    } else {
      totalSum += revList[i];
    }
  }
  return(totalSum%10 === 0 ? true : false);
};

batch.forEach(c => console.log(validateCred(c)));

【讨论】:

  • 你建议什么而不是反向?
  • 对代码的最小修改可能是从右到左迭代for (let i = revList.length - 1, i &gt;= 0; i--) ...
  • 可能还要加一个变量来检查奇偶,i不能用。
  • 为什么arr.reverse() 是个坏主意?奇数/偶数计算是从右到左的,所以它要么颠倒数字,要么从右到左。使用 reverse 使奇/偶计算更简单。
  • @RobG 因为它更改了原始数组,这可能不打算用于验证函数。
【解决方案2】:

重写并修复。

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];


function luhnCheck(num) {
  let digit, j, len, odd = true, sum = 0
  const digits = (num + '').split('').reverse()
  for (j = 0, len = digits.length; j < len; j++) {
    digit = parseInt(digits[j], 10)
    if ((odd = !odd)) digit *= 2
    if (digit > 9) digit -= 9
    sum += digit
  }
  return sum % 10 === 0
}

batch.forEach((item) => {
 let number = item.join('')
 console.log(number, luhnCheck(number))
})

理想情况下,您应该将其作为字符串传递并让函数进行拆分(关注点分离),就像在实际应用程序中您想在运行 luhn 之前对输入的数字执行各种操作一样.. cardTypeFromNumber(签证, maestro, dankort, mastercard, amex, dinersclub, discover, chinaunionpay (不使用 luhn), jcb 大多有所有不同的长度,除非你验证长度和格式,否则你不想运行 luhn), formatCardNumber, validateCardExpiry, validateCardCVC to举几个例子。

【讨论】:

  • 感谢您的时间和精力,但我现在不想让事情变得过于复杂,因为我还在学习基础知识。
  • 这只是一个练习,不是真实的。进行这些检查的唯一原因是在支付处理系统中的某个地方。从前端的角度来看,只需将其发送到支付 API 并让它完成所有工作。否则,您只是在双重处理和创建维护问题 - 新卡、类型、支票、数量和长度范围等 :-)
【解决方案3】:

Luhn algorithm 在维基百科上有解释。其他人已经回答了这个问题,这只是一个不同的实现。

function luhnCheck(cardNumber) {
  let nums = cardNumber.split('').reverse();
  let checkValue = nums.shift();
  let luhnSum = nums.reduce((sum, n, i) => {
    let val = n*(i % 2? 1 : 2);
    sum += val > 9? val - 9 : val;
    return sum;
  }, 0);
  return checkValue == 10 - (luhnSum % 10);
}


['4539677908016808', // valid1
 '5535766768751439', // valid2
 '4532778771091795', // invalid1
 '5795593392134643', // invalid2
 '344801968305414',  // mystery1
 '5466100861620239', // mystery2
].forEach(cardNum =>
   console.log(luhnCheck(cardNum))
);

【讨论】:

    猜你喜欢
    • 2021-07-21
    • 2012-02-29
    • 2019-03-11
    • 2012-01-05
    • 2014-12-25
    • 2013-10-21
    • 2016-01-12
    • 2020-02-28
    • 2017-01-09
    相关资源
    最近更新 更多