GP is right. You never do math with two credit card numbers as inputs. You can’t negate a credit card number, or find its absolute value, or square, etc.
It’s just a string of digits.
If the number already contains the check digit, drop that digit to form the "payload." The check digit is most often the last digit.
With the payload, start from the rightmost digit. Moving left, double the value of every second digit (including the rightmost digit).
Sum the digits of the resulting value in each position (using the original value where a digit did not get doubled in the previous step).
The check digit is calculated by 10 − ( s mod 10 ) {\displaystyle 10-(s\operatorname {mod} 10)} {\displaystyle 10-(s\operatorname {mod} 10)}.The issue is that many beginner (and some experienced) programmers treat what should be opaque strings as numbers and throw them into a 32/64-bit integer, or worse, a double precision float (in JavaScript). This can result in data corruption if not done carefully. Then, when something comes in to challenge the programmer's expectations, the program breaks. For example, ZIP/postal codes are 5 numeric digits in the US, but in CA, they're of the form "A1A 1A1" (notice the space and letters). JavaScript's `parseInt` will return NaN on a Canadian postal code. Another one is house numbers; They look numeric, but can have letters or even fractions(!) in them.
Does the number 21 "contain" the number 2? Not in a meaningful sense.
However, the string "21" definitely contains the substring "2".
The digits in a credit card number are meaningless. They have no relation to each other. If you choose two digits next to each other one doesn’t represent groups of 10x as much as the other digit. Or any other quantity.
The digits are effectively just symbols, not quantities like in a mathematical representation.
Credit card numbers are used with numerical operations