Remedial Activity: Credit Card¶
Topic Focus
(adapted from Introduction to Java Programming 10th Ed. by Y. Daniel Liang)
This activity focuses on strengthening mastery over the use of Loop Structures and arithmetic operations, specifically modulo and integer division. It introduces an alternative thought process of iterating through a sequence to achieve a result. The application of these areas into a real-life scenario are implemented through a very prevalent use of Functions to contain solutions to subproblems in this activity.
Let's create a program that will check if a credit card number is valid!
In 1954, Hans Luhn of IBM proposed an algorithm for validating credit card numbers.
The algorithm is useful to determine whether a card number is entered correctly, or whether a credit card is scanned correctly by a scanner.
Credit card numbers are generated following this validity check, commonly known as the Luhn check or the Mod 10 check, which can be described as follows (for illustration, consider the card number 4388 5760 1840 2626):
Task 1: Sum of Double Even Places¶
-
Double every second digit from right to left. If doubling of a digit results in a two-digit number, add up the two digits to get a single-digit number.

-
Now add all single-digit numbers from Step 1. $$ 4 + 4 + 8 + 2 + 3 + 1 + 7 + 8 = 37 $$
Write a function called sum_of_double_even_place() which takes in an integer input card_num and carries out the above two steps to return the sum of double the digits in even places.
Even Place Digits and Odd Place Digits
Note that here, we define even and odd placing based on the index of strings.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 4 | 3 | 8 | 8 | 5 | 7 | 6 | 0 | 1 | 8 | 4 | 0 | 2 | 6 | 2 | 6 |
- This means that the digits in even placing are (from left to right): 4, 8, 5, 6, 1, 4, 2, 2.
- The digits in the odd placing are (from left to right): 3, 8, 7, 0, 8, 0, 6, 6.
Tip 1: Iterating through Each Even Place Digit
You could first cast card_num into a string data type, and then retrieving each digit as they come from left to right - in fact, this is one way to go about the problem if you want to build this as a one-liner function.
One complication that could come here is that as soon as you retrieve each digit, you have to cast it into an int data type before being able to carry out the math operations on it.
Another way would be to retrieve the digits in a backwards fashion. That way, we can immediately use mathematical operations on it without needing to cast it back into an int format first. Also, the order in which you retrieve this digits does not matter. Going in a backwards direction would not impede how the summing works.
We can carry this out using a while loop:
| card.py | |
|---|---|
Note the use of the modulo/remainder % and the integer division // operators here.
However, as is, the given code will iterate through each digit regardless of whether it is even placed or not.
Modify the highlighted line such that it is able to skip to the next even place digit.
Tip 2: Retrieving Digit to Add to Sum
Given our example card number, the digits in the even place are (from right to left/back to front): 2, 2, 4, 1, 6, 5, 8, 4.
| Even Place Digit | Digit \(\times 2\) | \(\ge 10\)? | To Add |
|---|---|---|---|
| 2 | \(2\times 2 = 4\) | No | \(4\) |
| 2 | \(2\times 2 = 4\) | No | \(4\) |
| 4 | \(4\times 2 = 8\) | No | \(8\) |
| 1 | \(1\times 2 = 2\) | No | \(2\) |
| 6 | \(6\times 2 = 12\) | Yes | \(1 + 2 = 3\) |
| 5 | \(5\times 2 = 10\) | Yes | \(1 + 0 = 1\) |
| 8 | \(8\times 2 = 16\) | Yes | \(1 + 6 = 7\) |
| 4 | \(4\times 2 = 8\) | No | \(8\) |
We will include this process as part of the while loop procedure:
Note that here, when it comes to multiplying each retrieved digit by 2, the maximum result is 18 (\(9\times 2 = 18\)), which is 2 digit places long.
To sum each of these places up, using the modulo/remainder % and integer division // operators once to retrieve each digit place's value is enough.
Complete the addition process by adding the digit to total_sum.
Task 2: Sum of Odd Places¶
Add all digits in the odd places from right to left in the card number. $$ 6 + 6 + 0 + 8 + 0 + 7 + 8 + 3 = 38 $$
Write a function called sum_of_odd_place() which takes in an integer input card_num and returns the sum of the digits in odd places.
Task 3: Check Card Validity¶
-
Total up the two sums. $$ 37 + 38 = 75 $$
-
If this total is divisible by 10, the card number is valid; otherwise, it is invalid. In our example here, card number
4388 5760 1840 2626is invalid because \(75 \div 10 = 7 \text{ remainder } 5\). If you have a bank card with you, provided you followed and carried out the steps here correctly, your program should say that it is valid.
Write a function called is_card_valid() which takes in an integer input card_num and returns True if the card number is valid, or False otherwise.
Danger
If you decide to keep your solution in online storage like OneDrive or GitHub for instance, please ensure that you remove all traces of your card numbers! This is considered sensitive personal information, and you would do good to ensure that you do not unnecessarily put yourself at risk by revealing your bank card details to the whole world!
The example here shows an invalid credit card number, which poses no risk since at the time of putting this up, this number will not be used on any card out there.
Additional Task: Credit Card Categorization¶
Visa, Mastercard, and American Express are just 3 of several card networks used. Typically, the first 6 digits in a bank card number will define what is known as Bank Identification Numbers (BINs). Depending on which card network is being used, the first few digits in the BIN will take on some prefix by default. (Visit HERE for more information about this.)
For these three card networks, card numbers will generally start within the following prefix ranges:
| Issuing Network | Valid Prefixes |
|---|---|
| American Express (AMEX) | 34, 37 |
| Mastercard | 51 - 55 |
| Visa | 4 |
Write a function called get_issuer() which takes an integer input card_num and returns the name of the issuing network if any, and "No Issuing Network Found" otherwise.
Further Consideration for Checking Card Number Validity
How would you modify is_card_valid() to also check if the card number starts with a known prefix used by an issuing network?