Credit
クレジットカード (またはデビットカード) はもちろん、商品やサービスの支払いに使えるプラスチック製のカードです。カードに印刷された番号は特定のデータベースに保存されているため、カードが何かを買うために使われたときに、カード会社は誰に請求すれば良いのかを知ることができます。世界にはクレジットカードを持っている人がたくさんいるので、その数字はかなり長いといえるでしょう。American Expressは15桁の数字を使い、MasterCardは16桁の数字を使い、Visaは13桁あるは16桁の数字を使っています。これらは10進数 (0から9) であり、バイナリではありません。つまり、たとえば、American Expressは10^15=1000兆枚もの固有のカードを印刷できるということです。
実際には、クレジットカード番号には特定の構造があるため、これは少し誇張されています。すべてのAmerican Expressの番号は34または37で始まり、ほとんどのMasterCardの番号は51、52、53、54、または55から始まります (この問題では考慮しませんが、他の番号で始まる場合もあります) 。そして、すべてのVisaの番号は4から始まります。クレジットカード番号にも 「チェックサム」 が組み込まれており、少なくとも1つの番号と他の番号との間に数学的な関係があります。このチェックサムを利用すれば、コンピュータ (あるいは数学が好きな人間) は、データベースに問い合わせなくてもタイプミス (転位)を検出できます。もちろん、不誠実な数学者が、数学的側面を尊重しつつも偽の数字を作成する可能性は確かにありますから、より厳密なチェックのためにはデータベース検索が必要です。
Luhnのアルゴリズム
では、その構造とは何でしょうか。ほとんどのカードはIBMのHans Peter Luhn氏が開発したアルゴリズムを使用しています。Luhnのアルゴリズムによると、クレジットカード番号が (構造的に) 有効かどうかは、次のようにして判断できます。
- その数字の最後から2番目の数字から始め、1桁おきに2を掛け、それらの数を合計します。
- 2で乗算されなかった桁の数を合計します。
- 合計の最後の桁が0 (または、より正式に言えば、10を法として0に一致する) の場合、その番号は有効です。
ちょっとややこしいので、DavidのVisa: 4003600000000014を例に挙げてみましょう。
- 説明のために、数字の最後から2番目の数字から始め、1桁ごとに下線を引きます。
4003600000000014
では、下線の付いた各数字に2を掛けてみましょう。
1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2
すると、結果は以下のようになります。
2 + 0 + 0 + 0 + 0 + 12 + 0 + 8
次に、これらの積の和 (積の積ではなく) を計算します。
2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13
- 次に、その合計 (13) を、2を掛けなかった桁の合計 (末尾から開始) に加算します。
13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20
- その合計の最後の桁 (20) は0なので、Davidのカードは本物です!
そのため、クレジットカード番号を確認するのは難しくはないのですが、手作業は少々面倒です。プログラムを書きましょう。
実装の詳細
~/pset1/credit/
ディレクトリ内のcredit.c
という名前のファイルに、ユーザにクレジットカード番号の入力を求めるプログラムを記述し、ここに記載されている各フォーマットの定義に従って、American Express、MasterCard、Visaのカード番号のいずれかとして有効であるかを (printf
で) レポートします。コードのテストを自動化できるように、プログラムの出力の最後の行をAMEX\n
またはMASTERCARD\n
またはVISA\n
またはINVALID\n
にしてください。単純化するために、ユーザの入力はすべて数字 (すなわち、実際のカードに印刷されるようなハイフンがない) であると想定することができます。しかし、ユーザの入力がint
に収まると仮定しないでください。CS50のライブラリからget_long
を使用してユーザの入力を取得することをお勧めします。(なぜでしょうか?)
有効なクレジットカード番号 (ハイフンなし) が渡されたときのプログラムの動作を次に示します。
$ ./credit
Number: 4003600000000014
VISA
get_long
自体はハイフン (やその他) を拒否します。
$ ./credit
Number: 4003-6000-0000-0014
Number: foo
Number: 4003600000000014
VISA
しかし、クレジットカード番号ではない入力 (例えば、電話番号) を区別するのは、それがたとえ数字であっても、あなたがプログラミングする部分です
$ ./credit
Number: 6176292929
INVALID
プログラムを、有効な入力と無効な入力の両方でテストします (必ずそうします!)。PayPalがテスト用に推奨するカード番号をいくつか紹介しましょう。
入力によってプログラムが正しく動作しない場合 (またはまったくコンパイルできない場合) は、デバッグを開始します。
ウォークスルー
コードのテスト方法
check50
を使用して以下を実行し、コードの正確さを評価することもできます。ただし、必ず自分でコンパイルしてテストしてください。
check50 cs50/problems/2021/x/credit
以下を実行し、style50
を使用してコードのスタイルを評価します。
style50 credit.c
提出方法
次のコマンドを実行し、GitHubのユーザ名とパスワードを入力してログインします。セキュリティのため、パスワードには実際の文字ではなくアスタリスク (*
) が表示されます。
submit50 cs50/problems/2021/x/credit