14

クレジットカード番号の簡単な検証を実装しようとしています。ウィキペディアでLuhnアルゴリズムについて読みました:

  1. 右端のチェックディジットから数えて左に移動すると、2桁おきに値が2倍になります。
  2. 製品の桁(たとえば、10:1 + 0 = 1、14:1 + 4 = 5)を、元の数値の2倍にされていない桁と合計します。
  3. 10を法とする合計が0に等しい場合(合計がゼロで終わる場合)、その数はLuhnの式に従って有効です。それ以外の場合は無効です。

ウィキペディアでは、Luhnアルゴリズムの説明は非常に簡単に理解できます。ただし、 Rosetta Codeその他の場所(アーカイブ)でのLuhnアルゴリズムの他の実装も確認しました。

これらの実装は非常にうまく機能しますが、なぜ配列を使用して作業を行うことができるのかについて私は混乱しています。彼らが使用する配列はLuhnアルゴリズムとは関係がないようで、ウィキペディアに記載されている手順をどのように達成するかはわかりません。

なぜ彼らは配列を使用しているのですか?それらの重要性は何ですか、そしてウィキペディアで説明されているようにアルゴリズムを実装するためにどのように使用されていますか?

4

13 に答える 13

13

残念ながら、上記のコードはどれもうまくいきませんでした。しかし、私はGitHubで実用的なソリューションを見つけました

// takes the form field value and returns true on valid number
function valid_credit_card(value) {
// accept only digits, dashes or spaces
    if (/[^0-9-\s]+/.test(value)) return false;

// The Luhn Algorithm. It's so pretty.
    var nCheck = 0, nDigit = 0, bEven = false;
    value = value.replace(/\D/g, "");

    for (var n = value.length - 1; n >= 0; n--) {
        var cDigit = value.charAt(n),
            nDigit = parseInt(cDigit, 10);

        if (bEven) {
            if ((nDigit *= 2) > 9) nDigit -= 9;
        }

        nCheck += nDigit;
        bEven = !bEven;
    }

    return (nCheck % 10) == 0;
}
于 2013-11-29T08:53:22.023 に答える
9

この配列[0,1,2,3,4,-4,-3,-2,-1,0]は、0〜9の数値と、その値の2倍の桁の合計との差を見つけるためのルックアップ配列として使用されます。たとえば、番号8の場合、8と(2 * 8)= 16-> 1 + 6=7の差は7-8=-1です。

これはグラフィック表示です。ここで、{n}はnの桁の合計を表します

[{0*2}-0, {1*2}-1, {2*2}-2, {3*2}-3, {4*2}-4, {5*2}-5, {6*2}-6, {7*2}-7....]
   |       |        |         |        |        |       |         |  
[  0  ,    1    ,   2    ,    3  ,     4   ,   -4  ,   -3   ,    -2  ....] 

リストしたアルゴリズムは、すべての桁を合計し、偶数のスポット桁ごとに、配列を使用して差を調べ、それを合計に適用します。

于 2012-09-07T02:44:04.750 に答える
1

チェックサムを計算したい場合、このページのこのコードは非常に簡潔で、私のランダムテストでは機能するようです。

注:このページの検証アルゴリズムは、すべてが機能するわけではありません。

// Javascript
String.prototype.luhnGet = function()
{
    var luhnArr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]], sum = 0;
    this.replace(/\D+/g,"").replace(/[\d]/g, function(c, p, o){
        sum += luhnArr[ (o.length-p)&1 ][ parseInt(c,10) ]
    });
    return this + ((10 - sum%10)%10);
};

alert("54511187504546384725".luhnGet());​

これがC#に関する私の調査結果です

于 2012-09-13T00:31:54.307 に答える
1
function luhnCheck(value) {
  return 0 === (value.replace(/\D/g, '').split('').reverse().map(function(d, i) {
    return +['0123456789','0246813579'][i % 2][+d];
  }).reduce(function(p, n) {
    return p + n;
  }) % 10);
}

更新: これは文字列定数のない小さいバージョンです:

function luhnCheck(value) {
  return !(value.replace(/\D/g, '').split('').reverse().reduce(function(a, d, i) {
    return a + d * (i % 2 ? 2.2 : 1) | 0;
  }, 0) % 10);
}

ここでの 2.2 の使用は、5 を 9 に 2 倍にするときに、余分な 1 で 2 倍の d ロールオーバーを行うためのものであることに注意してください。

于 2015-02-14T02:26:48.800 に答える
0

コードは次のとおりです。

var LuhnCheck = (function()
{
    var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
    return function(str)
    {
        var counter = 0;
        var incNum;
        var odd = false;
        var temp = String(str).replace(/[^\d]/g, "");
        if ( temp.length == 0)
            return false;
        for (var i = temp.length-1; i >= 0; --i)
        {
            incNum = parseInt(temp.charAt(i), 10);
            counter += (odd = !odd)? incNum : luhnArr[incNum];
        }
        return (counter%10 == 0);
    }
})();

変数counterは、奇数の位置にあるすべての桁と偶数の位置にある桁の倍数の合計です。倍数が10を超える場合、それを構成する2つの数値を加算します(例:6 * 2-> 12-> 1 + 2 = 3)

あなたが求めている配列は、考えられるすべてのdoubleの結果です。

var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];

  • 0 * 2 = 0-> 0
  • 1 * 2 = 2-> 2
  • 2 * 2 = 4-> 4
  • 3 * 2 = 6-> 6
  • 4 * 2 = 8-> 8
  • 5 * 2 = 10-> 1 + 0-> 1
  • 6 * 2 = 12-> 1 + 2-> 3
  • 7 * 2 = 14-> 1 + 4-> 5
  • 8 * 2 = 16-> 1 + 6-> 7
  • 9 * 2 = 18-> 1 + 8-> 9

だから例えば

luhnArr[3] --> 6 (6 is in 3rd position of the array, and also 3 * 2 = 6)
luhnArr[7] --> 5 (5 is in 7th position of the array, and also 7 * 2 = 14 -> 5 )
于 2012-09-07T02:48:53.937 に答える
0

別の方法:

function luhn(digits) {
    return /^\d+$/.test(digits) && !(digits.split("").reverse().map(function(checkDigit, i) { 
        checkDigit = parseInt(checkDigit, 10);
        return i % 2 == 0
            ? checkDigit
            : (checkDigit *= 2) > 9 ? checkDigit - 9 : checkDigit;
    }).reduce(function(previousValue, currentValue) {
        return previousValue + currentValue;
    }) % 10);
}
于 2016-11-08T16:17:23.810 に答える