Jump to content

Talk:Luhn algorithm

Page contents not supported in other languages.
From Wikipedia, the free encyclopedia

Worked Example

[edit]

The only problem with this is that you get the same answer whether you start on the right hand side or the left hand side. It might be good to use a PAN with an even number of digits. —Preceding unsigned comment added by 125.236.50.155 (talk) 22:57, 27 November 2008 (UTC)[reply]

Patent 2950048

[edit]

http://www.pat2pdf.org/patents/pat2950048.pdf [1]

Page 4, Point 20 ~ 25

With numbers that result in 10 or greater are added together, not subtract 9. However when you are write computer code minus 9 is normally used.

ممكن اعرف انت في حياتي Maommad (talk) 11:51, 6 January 2021 (UTC)[reply]

No longer valid?

[edit]

Is this algorithm no longer valid? There are now VISA cards in circulation that fail this test but are legitimate cards.

May well be. In at least one country, Visa uses the last 3 digits (of 16) as a serial number for the same customer. So it may well be that we have to consider only the first 13 digits. —Preceding unsigned comment added by 117.193.104.83 (talk) 04:19, 4 May 2011 (UTC)[reply]

Created/Adopted When?

[edit]

The article states that the formula was adopted by credit card companies "late 1960s". But Luhn died in 1964, so wasn't creating much in the late 1960s. I suspect it's just a dangling modifier, and it should probably say that it was adopted in the late 1960s, shortly (or perhaps "not long", or "a few years") after its creation. However, without knowing the specifics of when it was created and when it was adopted, I'm not sure how to re-write. Darguz Parsilvan 6 July 2005 12:12 (UTC)

Resolved Discussions

[edit]

First Comment (Untitled)

[edit]

When converting every other digits (e.g. 8 -> 16 -> 7), the doubling step helps check for people who accidentally swapped adjacent digits (e.g. 1234->1243). But what's rationale behind converting 16 to 7?

My guess is that it keeps the overall numbers smaller, keeping things down to single check digits at each iteration.
The reason to do this is that it keeps the domain of the set the same. Converting 16 to 7 keeps a 1 to 1 ratio for each possible digit for the checkvalue. McKay (talk) 22:35, 30 September 2010 (UTC)[reply]
Technically you don't have to do that intermediate step, thanks to the associative and commutative properties of addition. You can just do the doubling and then add up all the individual digits for all the numbers in whatever order you want, and you can do mod 10 as often as you like along the way, as long as you do it once more after you add the last digit [so if the number is 6789 you could do: (1 + (2+7) + ((1+6+9) mod 10)) mod 10 and you get the same answer]. I think the author felt describing it with the values for each digit added up independently made it easiest for the reader to trace back the work to the original digits in the credit card number. Xcbsmith (talk) 21:48, 15 November 2011 (UTC)[reply]
The rationale behind converting 16 to 7 is to catch single-digit errors.
Perhaps this should be made more WP: obvious in the article.
The check digit article claims that "Systems with weights ... with the weights on neighboring numbers being different, are widely used [to detect] transposition errors. 1, 3, 7, and 9 are used because they are coprime to 10, so changing any digit changes the check digit; using a coefficient that is divisible by 2 or 5 would lose information (because 5×0 + 5×2 + 5×4 + 5×6 + 5×8 + 0 modulo 10) and thus not catch some single-digit errors."
This seems to imply that the Luhn algorithm (because it uses weights of 1 and 2) would not catch some single-digit errors. However, the Luhn algorithm actually does catch all single-digit errors, because it has that extra step -- *after* it weights the digits, it converts 16 to 7 etc.
If hypothetically someone were to incorrectly implement the Luhn algorithm after hastily reading a description of it and forgot to implement that step, he would have
(let's call this the "dumb algorithm"):
  1. From the rightmost digit, which is the check digit, moving left, double the value of every second digit. (For example, 8187 --> 16 + 1 + 16 + 7 is mis-written as 3187 --> 6 + 1 + 16 + 7)
  2. Take the sum of all the resulting values. (16 + 1 + 16 + 7 = 40, while 6 + 1 + 16 + 7 = 30)
  3. If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid according to the dumb formula; else it is not valid. (We want the check algorithm to detect and reject single-digit errors like this one, but in this case it fails to detect the error).
For the reasons that McKay and Xcbsmith stated, with this dumb algorithm, a transcription error -- in a position that will be doubled -- that changes "5" to "0", or "6" to "1", or "7" to "2", or "8" to "3", or "9" to "4", or vice-versa, will be undetected.
The extra step in the Luhn algorithm -- "if the product of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then sum the digits of the product" -- allows the Luhn algorithm to detect *any* single-digit transcription error.
How can we make this more obvious to people reading this article, without getting bogged down in unnecessary detail? --DavidCary (talk) 15:58, 22 December 2015 (UTC)[reply]
How about we just say that after the doubling step you add up all the digits modulo 10? Or perhaps say you add up, discarding all but the last digit along the way? Xcbsmith (talk) 02:05, 6 October 2016 (UTC)[reply]

Strengths/Weaknesses

[edit]

The Luhn formula will catch any single-digit error. It will also catch almost any transposition of adjacent digits (e.g., 18 <-> 81). There is one adjacent-digit transposition that Luhn will not catch: 09 <-> 90. It would be a prudent step for applications using Luhn to refrain from issuing numbers with 09 and/or 90 in them, so that this particular transposition cannot result in another valid number. The Verhoeff check digit formula (not currently described in Wikipedia) might be a better choice, since it catches all adjacent-digit transposition errors. Richwales 21:17, 14 April 2006 (UTC)[reply]

The Verhoeff algorithm is described now. Richwales 00:06, 20 April 2006 (UTC)[reply]

The Pseudocode Is Wrong

[edit]

The given pseudocode is incorrect. The for loop must iterate from 0 to (nDigits - 1), not to nDigits. Iterating to the length of a zero-based array will exceed the upper bound of the array. For example, an array Arr[] of only one element has a length of 1, but the only valid entry is Arr[0]. The loop presented would attempt to check both Arr[0] and Arr[1], exceeding the upper bound of the array. In memory-managed environments this will generate a runtime error; in C, it's interesting pointer arithmetic resulting in the inclusion of a more-or-less random memory location as an unintended digit of the number being checked. A good compiler may catch the error.

Also, the general purpose of pseudocode is to be illustrative. As such, it would be more informative to use modulus 2 in place of AND 1. AND 1 is a programming optimization which exploits a bitwise AND to perform the same logical operation as modulus 2. AND 1 is used in programming solely because it generally compiles to faster executable code than does modulus 2. However, speed optimization is rarely the point of pseudocode. The use of modulus 2 would relate the pseudocode more directly to the informal discussion in the article, and make the pseudocode easier to follow for a more general audience.

You are absolutely right, and indeed argue with too much force; both seem clearly good changes to me. I also changed XOR to ≠. The result seems a lot simpler. In the future I encourage you to be bold and make changes yourself, as well as leave a note on the talk page, if you wish. Deco 06:26, 7 Jan 2005 (UTC)
Woah now, isn't the pseudo code supposed to go from nDigits - 1 down to 0? This is the first I've read the algorithm, and the words don't match the code. If I was sure which was correct I'd fix it. --Nofxjunkee 17:21, 20 September 2006 (UTC)[reply]
You are correct. According to Vital (Now TSYS) the wording is correct and the pseudo-code is wrong. I have recommended that it be changed. Have to be careful though in how you word the for loop cause not all languages implement for the same. While loops may be safer and more language independant. --dmprantz 17 October 2006 (UTC)


Computing the check digit

[edit]

The algorithm stated checks if a number is valid according to the Luhn algorithm, but does anyone have an algorithm that computes a Luhn check digit, i. e. modifies an existing number by appending a digit so that the result is Luhn valid? I mean, something smarter than trying the ten possible digits until the matching one is found. - wr 10-oct-2006

Agreed, but the code for this would be so similar to the CreateNumber example as to get repetitive (based on idea that this is not code repository). Would it be more relevant to replace CreateNumber with GetCheckDigit? Probably best to just go with one or the other. Would be happy to post calc function if deemed more relevant than existing CreatNumber. Skratowicz 03:31, 29 June 2007 (UTC)[reply]
The algorithm to create the check digit the same algorithm, with an extra step at the end. Put 0 in as a temporary placeholder for the check digit, then calculate the sum (as explained in the article). Calculate the sum modulus 10. If the result is 0, then you're done - the check digit is zero. Otherwise, the check digit is 10 - (sum modulus 10). Using the example from the article, we start with the base account number of 499273987x, where x is the check digit. Substitute zero for x, and the calculations are: 0 + (2) + 7 + (1+6) + 9 + (6) + 7 + (4) + 9 + (1+8) + 4 = 64 (compare to step 2 in the main article's illustration). 64 modulus 10 is 4, so the check digit is 10-4, or 6. 205.210.222.150 (talk) 14:15, 16 April 2009 (UTC) Jim Hyslop[reply]

Comments on Changes

[edit]

This article was just plain wrong in the way it was worded. It talked about "calculating" a checksum digit, but explained how to VERIFY a checksum digit. Two slightly different tasks. I changed the text to match the algorithm since that is the most commonly used purpose. I tried to remove everything that didn't make sense. If some one really wants to add back in an area for calculating the checksum digit, by all means do so, but please be precise and clear.

Responses to various Talk Topics:

Computing the check digit is a simple excercise of mathematics, and a well written Luhn Algorithm will be able to do it with little stress. Implementation is left as an excersize.

The Mod 10 (Luhn) algorithm is very much valid. If you know of any Visa numbers that do not pass it, please elaborate, but my business depends on it, and there is no notice of which I am aware which depricates this algorithm.

The current state of the pseudocode is still wrong IMHO, and at least one other person agrees. The algorithm, as it is stated, goes from the end to the beginning, so make the pseudo-code loop go from the end to the beginning. Don't ever bother checking for this parity value that only stands to confuse the reader....if the pseudo-code goes from right to left with if statements, restate the algorithm to do the same. I have seen far too many implementations that take this crazy turn:( Also, ADD SOME CURLY BRACES!!!! Allow me to paraphrase Larry Wall: "Even if you aren't in doubt, consider the mental welfare of the person who has to read the code after you, and who will probably put braces in the wrong place."

Before any one tells me to be bold, please don't. Mod 10 is part of my business. As much as I would like to help the world understand the algorithm, I cannot share my knowledge without giving away my business' IP. I am glad to remove inaccuracies and to point others in the right direction, but creation of any specific code (pseudo or real) can get me into trouble. Sorry. :( --dmprantz 17 October 2006 (UTC)

Anyone else surprised by the notion that someone's living hinges on having superior knowledge of how to implement Mod 10 decimal digit sums. I'd love to see a description of what this kind of job *is* in the article. — Preceding unsigned comment added by Xcbsmith (talkcontribs) 21:54, 15 November 2011 (UTC)[reply]

Fixed Algorithm Section

[edit]

I rewrote the algorithm and included a complementary one. I use a boolean flag instead of a mod 2 or and 1 to make the code simpler and more similar to the text. Feedback? ZX2C4 08:14, 6 January 2007 (UTC)[reply]

I'd like to make some changes. The PHP algorithm calls the digits to be double Luhn Digits. In the original patent, Luhn calls them substitution digits. Also in this algorithm, I think it is odd to convert the subsitution digit to a string just to find out that its ten's digit is one. We know that. The C# algorithm is more direct on this. Concerning the C# alternating flag thing, well, since taking a number mod 2 is (or should be) implemented as bit-wise AND with 1, I would stick w/ mod 2. It's clearer what's going on, the code is all in one place, and it might be even faster in use. But I will differ to the person who took the time to write this excellent code.
Finally, as for creating the check digit, I don't think that code is what we want. The question is: what digit should I add to a particular number? If we assume that we will get a k digit number, and will add the check-digit as the least-significant number and return a k+1 digit number. --Ozga 14:42, 14 December 2006 (UTC) --Ozga 14:36, 24 August 2007 (UTC)[reply]

I think if you factor your equation above and adjust for the modulo implementation I use, you'll come up the same thing, unless you are mistaken. I have double checked the last part of the algorithm. Essentially the algorithm figures out what the Luhn sum would be for the number sequence with out the check number. Then it determines what mod 10 of that number is. If mod 10 is 0, then the number already passes, so the check is 0. Otherwise, a value needs to be added so that the sum + check mod 10 will be zero. Therefore, we do 10 minus the sum mod 10 to determine the check digit. If you're unhappy with the logical defense of last step, you can observe it empirically by compiling the test program here: [2]. I have added a new section below regarding the improper addition of the php and vb algorithms. ZX2C4 08:14, 6 January 2007 (UTC)[reply]

I agree with the math, and apologize if it seemed like I didn't acknowledge the correctness of your algorithm. What I meant was, to present code that takes as argument a string of digits that lacks a checksum digit, and returns that string with the appropriate digit appended so the result passes the checksum, or some similar functionality. --Ozga 04:53, 26 May 2007 (UTC)[reply]

Removal of VB and PHP Algorithms

[edit]

The VB/VB.net algorithm was not valid vb.net. Both algorithms introduced extraneous complexities that utilize more concepts than necessary to demonstrate the Luhn algorithm. Wikipedia is an encyclopedia, not a code repository, and for this reason, these two extra algorithms have been removed. The C# algorithm is the most straightforward and does not introduce unnecessary concepts. The C# algorithm is also consistent in its coding to the following algorithm that generates Luhn sequences. ZX2C4 08:05, 6 January 2007 (UTC)[reply]

Algorithms

[edit]

Many people must be interested in links to the algorithms! As a compromise, let's just keep them on the discussion page, shall we? PLEASE don't delete these! Most of us don't care for C#! Paperweight 21:18, 28 February 2007 (UTC)[reply]

I've moved these links to a section on the main page, complying with the compromise. --ZX2C4

Mathematica implementation

[edit]

Still missing this one :) LuhnCheck[n_] := Module[{digits = IntegerDigits[n]}, For[i = Length[digits] - 1, i >= 1, i -= 2, digits[[i]] = FixedPoint[Composition[Total, IntegerDigits], 2*digits[[i]]]]; Mod[Total[digits], 10] == 0 ] 11:42, 28 December 2007 (UTC)

JavaScript implementation is wrong

[edit]

There are at least two errors in the javascript implementation linked to in the article here. The 'if' check to see if a digit is longer than 9 "if( clen [n] > 9 ) clen [n]-=9;" should be inside of the preceding 'for' loop or in it's own or else it doesn't do anything and there is a closing curly bracket that ends the function before the function is complete (line 13 in the linked to code). I'm not sure about the other implementations but this one is wrong so I have removed it until it can be replaced by a correct implementation. —Preceding unsigned comment added by 24.207.187.11 (talk) 07:08, 14 September 2008 (UTC)[reply]

Implementation in Scheme

[edit]

I noticed that the current link to the Implementation in Scheme, although a working implementation, is not a particularly Scheme-like example in that it uses iteration and variable mutation rather than tail-recursion which is far more typical of a Scheme function. Can I propose that we include a link to my own implementation which is tail-recursive. This will give Schemers a choice of the two implementations. Unfortunately, I edited the page to include my own link but found that it had been reverted because it's on a blogspot URL so was told to post a note here instead. —Preceding unsigned comment added by 62.189.169.182 (talk) 09:12, 7 November 2008 (UTC)[reply]

Excel code does not work in Excel 2008 for Mac

[edit]

The code provided as the Excel example does not work in Microsoft Excel 2008 for Mac. I've commented it out in the article but left the code intact. I apologize if this is not the correct way to deal with this issue. Can this code please be checked for accuracy?

Thank you.

Christofer C. Bell (talk) 01:50, 14 March 2010 (UTC)[reply]


Error in Ruby Algorithm

[edit]

Can anyone check the ruby algorithm? It clearly fails on validating some valid credit cards where the JS version returns true.

--85.179.130.223 (talk) 16:49, 1 April 2010 (UTC)[reply]

Example implementation incorrect

[edit]

If a digit 9 is to be doubled, the example implementation will add in (9 * 2) % 9, or 0. The actual algorithm would add a 9. Given that the final sum is taken mod 10, it'll be 1 too high for every doubled 9 in the original number.

I've fixed this. It somewhat complicates the code, but it's clearly incorrect otherwise. 98.111.85.57 (talk) 17:01, 3 May 2010 (UTC)[reply]

JavaScript implementation added, with permission.

[edit]

I copied the source code from: https://sites.google.com/site/abapexamples/javascript/luhn-validation And the author allow me to remove the credit. (for wiki). —Preceding unsigned comment added by 79.181.25.30 (talk) 21:30, 15 January 2011 (UTC)[reply]

10+5 ?

[edit]

I really doubt that the 10+5 variant would actually be used somewhere... First, why would it be called 10+5 instead of "mod 5"? Second, why would someone use a much worse checksum -- I don't think the nice properties of the Luhn algorithm transfer to the mod 5 variant. Third, what would be the reason for not using the original Luhn?

I suggest removal or a reference to some proof... 62.78.167.76 (talk) 13:48, 23 January 2011 (UTC)[reply]

Implementations

[edit]

More implementations of the algorithm are not needed in the article, as Wikipedia is an encyclopedia and not a programming tutorial. Here's what the draft of the WikiProject Computer Science manual of style has to say about the number of code samples:

Multiple source code implementations are not appropriate unless they contrast specific aspects of the code and that contrast is important to the encyclopedic content of the article. If possible, accentuate differences by providing the alternate implementation in the same language as the original.

Acdx (talk) 03:14, 7 February 2011 (UTC)[reply]

- Agreed. C is far too verbose, unclear, and distracting... Fortran and PHP are not really relevant here - I doubt anyone is implementing something like this in either language. I've removed them leaving Java, Python, and Groovy, with justifications for each. Java is obviously a mainstream language which many will look for, Python implements the algorithm very concisely, and Groovy is a good balance between the two, and I feel illustrates the algorithm without any distractions (i.e. the sumTable in Java or the slice operator in Python). I think between the 3 the algorithm is properly demonstrated. (A C# implementation is probably the only thing missing) RebelBodhi (talk) 03:20, 9 May 2011 (UTC)[reply]
- I disagree with the assessment on PHP. Removing C and Fortran seems valid, but PHP is in fact one of the most popular programming languages on the web and is used by a large number of e-commerce sites. Computing Luhn in PHP is not at all uncommon and it is instructive to see the novel approach that was used here. Isnoop (talk) 00:27, 18 May 2011 (UTC)[reply]

Errors in the examples

[edit]

Both the C# implementation and the Scala implementation seems wrong to me. The algorithm states "Counting from the check digit, which is the rightmost, and moving left, double the value of every second digit". Then, shouldn't the example read:

bool isLuhnValid(string s)
{
    return s.Reverse().SelectMany((c, i) => ((c - '0') << (i & 1)).ToString()).Sum(c => (c - '0')) % 10 == 0;
}

Similarly for Scala, shouldn't it be:

def isLuhnValid(s : String) = 
    s.reverse.zipWithIndex.map({ case (c, i) => ((c - '0') << (i & 1))}).mkString.map(_ - '0').sum % 10 == 0

Rehno Lindeque (talk) 09:33, 1 June 2011 (UTC)[reply]

Haskell example

[edit]

I added a haskell example that elegantly describes the algorithm from a high level as "reverse the string", "convert to digits", "double every second element", "convert to a string", "convert to digits", "sum them all up". Rehno Lindeque (talk) 11:01, 1 June 2011 (UTC)[reply]

Remove all implementation examples

[edit]

I propose that all of the code examples be removed as they add nothing to the understanding of the topic. All of them are examples obfuscated code and in most cases the obfuscation is done purely for code golf reasons. This goes against the draft computer science manual of style which says:

The sample should use a language that clearly illustrates the algorithm to a reader who is relatively unfamiliar with the language — even if you believe that the language is well-known. To remain language-neutral, choose languages based on clarity, not popularity. Avoid esoteric or language-specific operations.

All of the examples provided voilate this guideline is spectacular fashion. Most of them would be considered bad style even amongst programmers familiar with the languages due to the obfuscation making the code hard to check for correctness (see above -- many times). It would not be surprising if some of them were far from optimal too, as is often the case when playing code golf.

If someone doesn't understand the the algorithm from the informal explanation, they certainly aren't going to understand it from these code examples. A simple pseudocode example would be much better. The presence of obfuscated one liners only encourages others to add another obfuscated one liner for their favourite programming language. Woonix (talk) 18:18, 1 June 2011 (UTC)[reply]

Agree completely. A simple pseudocode algorithm should be crafted and all other examples removed. – Acdx (talk) 13:56, 28 July 2011 (UTC)[reply]

Everyone seems to agree, so I've done this. 98.182.22.49 (talk) 23:23, 1 June 2019 (UTC)[reply]

For the record, I don't agree at all. I consider this another example of a Wikipedia article going from something useful to something meaningless. Mlewan (talk) 07:18, 2 June 2019 (UTC)[reply]
Mlewan, I write software for a living, and I assure you it's still plenty useful. Anyone who wants to check digits in their code can just translate the pseudocode to their language of choice, which is trivial for any developer (or they'll just use a library that implements it).
I'm not just implementing policy for policy's sake. In fact, I almost never edit pages at all. I only bothered to change it because I ran into it at work and thought "Wow, that's excessive and pointless. I'm going to check the talk page to see what's going on here." This brings it in line with other algorithm pages, such as Quicksort or A*. 98.182.22.49 (talk) 22:40, 2 June 2019 (UTC)[reply]

Python Example

[edit]

If anyone is interested, I've cleaned up the python code a bit to make it easier to understand for newer programmers. I used a less "clever" implementation, and tried to name variables more clearly. I also consolidated the checksum code, so it is implemented once, and used in two ways to check validity, and to find the last digit.

I've also put up a gist on github with the code and tests showing correctness. https://gist.github.com/1773914

def luhn_checksum(card_number):
    def digits_of(n):
        return [int(d) for d in str(n)]
    digits = digits_of(card_number)
    odd_digits = digits[-1::-2]
    even_digits = digits[-2::-2]
    checksum = 0
    checksum += sum(odd_digits)
    for d in even_digits:
        checksum += sum(digits_of(d*2))
    return checksum % 10

def is_luhn_valid(card_number):
    return luhn_checksum(card_number) == 0

def calculate_luhn(partial_card_number):
    return 10 - luhn_checksum(int(partial_card_number) * 10)

206.169.213.106 (talk) 21:08, 8 February 2012 (UTC)[reply]

It looks good. I've put this version up in the article. – Acdx (talk) 11:55, 18 February 2012 (UTC)[reply]

I believe the Python implementation is incorrect. First, it does not work with zero padding. The leading zero/s will cause the str function to treat the number as an octal number which is not what you want. Secondly, calculate_luhn returns (10 - something_mod_10). Hence, the results will be between 1 and 10, which is not what we want for a single checksum digit. 216.165.126.85 (talk) 01:05, 17 March 2012 (UTC)[reply]

The Python example doesn't clarify anything. I have done minor programming with BuildBot; which I believe uses Python. I have used Perl, lisp, Basic, C, Java, C++, 8 different assembler languages, JavaScript, Pascal and Fortran. Any programmer who can not look at the table at the start and not translate it to the language they are using should not be programming. This is not a statement against Phyton. It is for the title of this section; remove all programming languages. I agree with this. 71.19.161.130 (talk) 20:51, 5 November 2014 (UTC)[reply]
Agreed. American Express cards, in particular, use zero padding to adjust the position of the numbers. More concerning to me, however, is that this example is uncited and looks more like original research until you read this discussion, which no one should have to do. Then again, the code example was changed without a source, and thus... Nulbyte (talk) 21:00, 8 July 2015 (UTC)[reply]

Ruby Solution

[edit]

Here is a basic Ruby solution to luhn10 validation. I decided to place it here instead of the article.

def luhn10?(number)
    checksum = 0
    digits = split_integer(number).reverse
    digits.each_with_index do |d,i|
      checksum += i % 2 == 1 ? sum_digits(d*2) : d
    end
    (checksum % 10) == 0
  end
  def split_integer(number)
    digits = []
    number.to_s.split('').each do |digit|
      digits << digit.to_i
    end
    digits
  end
  def sum_digits(number)
    split_integer(number).inject(0){ |sum,digit| sum += digit.to_i} 
  end

— Preceding unsigned comment added by [[User:{{{1}}}|{{{1}}}]] ([[User talk:{{{1}}}|talk]] • [[Special:Contributions/{{{1}}}|contribs]])

Bug fixes. Boud (talk) 21:23, 24 February 2015 (UTC)[reply]

description incorrect 4/17/2013

[edit]

1.From the left most digit, moving right, double the value of every second digit

This is incorrect; it works with odd-length numbers, like the example, but not even-length, like most credit cards.

Reading the edits, it looks like it was originally written differently (from the rightmost digit, moving left...), but the confusion is in what is being described- creating a check digit for a number or validating a number with a check digit. The current description is creating a check digit for a number, so "from the rightmost digit, moving left..." is also incorrect, since the original number does not have the check digit. "From the rightmost digit, moving left..." is correct for validating a number with a check digit. — Preceding unsigned comment added by 64.193.143.107 (talk) 19:01, 17 April 2013 (UTC)[reply]

C example bogus

[edit]

I'm not going into details, but there's simply too much wrong with the C implementation. The link needs to be removed or the author needs to fix this. --eNTi (talk) 20:57, 13 May 2015 (UTC)[reply]

APL Implementation

[edit]
Luhnc←{10|-+/,0 10⊤⍵×⌽(≢⍵)⍴2 1}  ⍝ calculate the check digit
Luhnv←{(⊃⌽⍵)≡Luhnc ¯1↓⍵}         ⍝ verify the check digit

      x← 7 9 9 2 7 3 9 8 7 1
      Luhnc x
3
      Luhnv x,3
1

A team effort of the "Array Oriented Functional Programming with Dyalog" workshop at FunctionalConf '16.   Roger Hui (talk) 10:41, 16 October 2016 (UTC)[reply]

Confusion about check digit

[edit]

I am very confused. Why do some of the implementations completely ignore the check digit and others don't? And why would the digit be ignored? — Preceding unsigned comment added by Sollyucko (talkcontribs) 18:29, 4 April 2019 (UTC)[reply]

"third row": what&where is it?

[edit]

Twice, the "Description" mentions a "third row". I have no idea where that third row is and what it contains. What are rows one&two? — Preceding unsigned comment added by 146.60.210.112 (talk) 14:40, 21 July 2019 (UTC)[reply]


I noticed the row mystery. Overall, this article is the worst description of anything I ever saw. Absolutely useless.

Pseudocode

[edit]

I’ve no idea what this is supposed to be doing. It looks incomplete as well as incorrect. Nick Levine (talk) 08:29, 11 May 2020 (UTC)[reply]

Formula error

[edit]

The sentence "The check digit is calculated by 10 - (s mod 10)." is not correct. If 's' is a multiple of 10 then the formula result is 10, which is not a digit. To correct this, the sentence should be updated to say "The check digit is calculated by (10 - (s mod 10)) mod 10.". — Preceding unsigned comment added by 64.231.116.243 (talk) 02:13, 20 June 2022 (UTC)[reply]

pseudocode

[edit]

Three comments on the pseudocode:

int parity := (nDigits-2)modulus 2

First, there is no such operation as "modulus". The operation is called "modulo" or "mod" for short. The "modulus" is the second operand in a mod operation (in this case, 2) not the operation or the result of the operation. Second, unless card numbers can have no digits other than a check digit, "(nDigits-2) mod 2" is equal to "nDigits mod 2". Third, type declarations and casts are undesirable in pseudocode unless the meaning of the code is unclear without them. Zerotalk 05:58, 7 October 2022 (UTC)[reply]

One alternative formula is wrong

[edit]

The formula 10[s/10] -s is wrong as written. The use of integer math is implied, for if fractional values are allowed, the formula is zero for all s. With internet arithmetic and given example where’s=67, the formula gives -7, not the correct answer of 3. I would suggest it be r)e-written as 10 + { INT(10[s/10])- s} Or perhaps better 10-{ s - INT( 10[s/10])} This Alternative formula gives 3, but I have not carefully checked that it agrees with Luhn’s original formula. Alternatively, just delete that line in the article. GWT45 (talk) 04:10, 6 February 2023 (UTC)[reply]

I think you've misread the formula: it's using the "ceiling" operator rather than square brackets. If s=67, then . So the full equation evaluates to 3.
The first equation does look wrong though, since it'd result in 10 rather than 0 if s is a multiple of 10. James (talk) 10:54, 4 July 2023 (UTC)[reply]

Unnecessarily complex implementations

[edit]

Why do all these implementations do the unnecessary steps of separating the check digit from the payload, subtracting the weighted payload sum from 10 and comparing it with the check digit?

All you have to do is leave the check digit as part of the payload, weight that position as 1, mod the the whole sum by 10 and compare it to 0. Tzadik (talk) 12:13, 4 January 2024 (UTC)[reply]

the C# example

[edit]

The code is not correct, nor does it bring a correct result. לומד (talk) 08:26, 21 February 2024 (UTC)[reply]

How is it wrong? Can you explain what the problem is, or give an example of an input that causes it to have the wrong output?
Solomon Ucko (talk) 14:44, 21 February 2024 (UTC)[reply]
- `in int[1] digits` doesn't compile because of the `1` (unless this is an upcoming feature of the language, but even so we probably don't want an array with only one element)
- whether it "doubles" a digit is based on its index from the start, not the end, of the input
- if the check digit needs to be 0, the code instead checks that it is 10
There used to be a working example, but all the examples were deleted (see "Remove all implementation examples" above) and someone has since added this one instead. Rawling (talk) 10:09, 9 March 2024 (UTC)[reply]

Is the final step in calculating the checksum actually correct?

[edit]

According to the article, the last step is "The check digit is calculated by ". Unfortunately, following this logic, it would be IMPOSSIBLE for the check digit to ever equal 0. The value returned by can only range between 0 and 9. So when you subtract that number from 10, you get a value that ranges between 10 and 1. This set of numbers is completely missing a 0, and it also includes a 10 which is too large for a single digit. The article here doesn't mention how this is to be fixed. I would assume if the output is 10 then it would then just be converted to 0 in an additional final step, but that's not mentioned anywhere in the article, so I'm not sure how that should actually be handled. 73.169.149.34 (talk) 20:16, 27 September 2024 (UTC)[reply]