1. 程式人生 > >銀行卡號校驗位的LUHN演算法模10“隔位2倍加”校驗數的公式

銀行卡號校驗位的LUHN演算法模10“隔位2倍加”校驗數的公式

 銀聯卡卡號由三部分組成:髮卡機構標識碼(bin)、髮卡機構自定義位、校驗碼。其中,卡號左起前六位是髮卡機構標識程式碼(BIN),由6位數字組成。BIN號由中國銀聯複製分配、確認和管理;卡號第七位起事發卡機構自定義位,由6至12位數字組成,髮卡機構自行賦值;卡號最後一位是校驗碼,根據校驗位前的數字(含BIN)取值Luhn方程計算得出。

計算LUHN演算法模10“隔位2倍加”校驗數的公式


  計算步驟如下:

  步驟1:從右邊第1個數字(低序)開始每隔一位乘以2。
  步驟2:把在步驟1中獲得的乘積的各位數字與原號碼中未乘2的各位數字相加。
  步驟3:從鄰近的較高的一個以0結尾的數中減去步驟2中所得到的總和[這相當於求這個總和的低位數字(個位數)的“10的補數”]。如果在步驟2得到的總和是以零結尾的數(如30、40等等),則校驗數字就是零。
  例:
    無校驗數字的卡號 4992 73 9871 
  4 9  9 2 7 3 9 8 7 1       
   ×2    ×2     ×2    ×2    ×2
   18    4    6   16    2

  4+1+8+9+4+7+6+9+1+6+7+2=64        
  70-64=6                 

  帶有校驗數字的卡號為:4992 73 9871 6


excel當中的校驗公式

:假設卡號在A2單元格中,公式可以計算出賬號最後一位的校驗位數字

=MOD(SUM(-MID(TEXT(MMULT((0&MID(LEFT(A2,LEN(A2)-1),ROW($1:$9)*2-MOD(LEN(A2)+{0,1},2),1))*{1,2},{100;1}),"000"),{1,2,3},1)),10)

陣列公式,要按shift+ctrl+enter結束
求魔方當中的公式應該怎樣寫呢?
(銀聯要求的卡號是13-19位此程式碼要滿足13-19位卡號的計算)

答覆:

完整支援16-19位銀號卡號校驗位計算:

text(mod((left(right($MF(賬號)$,3),1)+left(right($MF(賬號)$,5),1)+left(right($MF(賬號)$,7),1)+left(right($MF(賬號)$,9),1)+left(right($MF(賬號)$,11),1)+left(right($MF(賬號)$,13),1)+left(right($MF(賬號)$,15),1)+mod(left(right($MF(賬號)$,2),1)*2,10)+int(left(right($MF(賬號)$,2),1)*2/10)+mod(left(right($MF(賬號)$,4),1)*2,10)+int(left(right($MF(賬號)$,4),1)*2/10)+mod(left(right($MF(賬號)$,6),1)*2,10)+int(left(right($MF(賬號)$,6),1)*2/10)+mod(left(right($MF(賬號)$,8),1)*2,10)+int(left(right($MF(賬號)$,8),1)*2/10)+mod(left(right($MF(賬號)$,10),1)*2,10)+int(left(right($MF(賬號)$,10),1)*2/10)+mod(left(right($MF(賬號)$,12),1)*2,10)+int(left(right($MF(賬號)$,12),1)*2/10)+mod(left(right($MF(賬號)$,14),1)*2,10)+int(left(right($MF(賬號)$,14),1)*2/10)+mod(left(right($MF(賬號)$,16),1)*2,10)+int(left(right($MF(賬號)$,16),1)*2/10)+if(len($MF(賬號)$)>=17,left(right($MF(賬號)$,17),1),0)+if(len($MF(賬號)$)>=18,mod(value(left(right($MF(賬號)$,18),1))*2,10)+int(value(left(right($MF(賬號)$,18),1))*2/10),0)+if(len($MF(賬號)$)>=19,left(right($MF(賬號)$,19),1),0))*9,10),0)

配圖


配合銀行BIN碼的檢查,就可以知道銀行卡是出自哪個銀行。

功德圓滿
16-19位的校驗位公式
text(mod((left(right($MF(賬號)$,3),1)+left(right($MF(賬號)$,5),1)+left(right($MF(賬號)$,7),1)+left(right($MF(賬號)$,9),1)+left(right($MF(賬號)$,11),1)+left(right($MF(賬號)$,13),1)+left(right($MF(賬號)$,15),1)+mod(left(right($MF(賬號)$,2),1)*2,10)+int(left(right($MF(賬號)$,2),1)*2/10)+mod(left(right($MF(賬號)$,4),1)*2,10)+int(left(right($MF(賬號)$,4),1)*2/10)+mod(left(right($MF(賬號)$,6),1)*2,10)+int(left(right($MF(賬號)$,6),1)*2/10)+mod(left(right($MF(賬號)$,8),1)*2,10)+int(left(right($MF(賬號)$,8),1)*2/10)+mod(left(right($MF(賬號)$,10),1)*2,10)+int(left(right($MF(賬號)$,10),1)*2/10)+mod(left(right($MF(賬號)$,12),1)*2,10)+int(left(right($MF(賬號)$,12),1)*2/10)+mod(left(right($MF(賬號)$,14),1)*2,10)+int(left(right($MF(賬號)$,14),1)*2/10)+mod(left(right($MF(賬號)$,16),1)*2,10)+int(left(right($MF(賬號)$,16),1)*2/10)+if(len($MF(賬號)$)>=17,left(right($MF(賬號)$,17),1),0)+if(len($MF(賬號)$)>=18,mod(value(left(right($MF(賬號)$,18),1))*2,10)+int(value(left(right($MF(賬號)$,18),1))*2/10),0)+if(len($MF(賬號)$)>=19,left(right($MF(賬號)$,19),1),0))*9,10),0)

package com.cup.tracy;

public class Luhn {
	/**
	 * Luhn演算法
	 * 根據卡號獲取校驗位
	 * @param cardNumber
	 * @return
	 */
	public static int getCheckNumber(String cardNumber){
		int totalNumber = 0;
		int lastNumber = 0;
		for (int i = cardNumber.length()-1; i >= 0; i-=2) {
			int tmpNumber = calculate(Integer.parseInt(String.valueOf(cardNumber.charAt(i))) *  2);
			if (i==0) {
				totalNumber += tmpNumber;
			}else {
				totalNumber += tmpNumber + Integer.parseInt(String.valueOf(cardNumber.charAt(i-1)));
			}
			
		}
		if (totalNumber >= 0 && totalNumber < 9) {
			return (10 - totalNumber);
		}else {
			String str = String.valueOf(totalNumber);
			if (Integer.parseInt(String.valueOf(str.charAt(str.length()-1))) == 0) {
				return 0; 
			}else {
				return (10 - Integer.parseInt(String.valueOf(str.charAt(str.length()-1))));
			}
		}
		
	}
	
	/**
	 * 計算數字各位和
	 * @param number
	 * @return
	 */
	public static int calculate(int number){
		String str = String.valueOf(number);
		int total = 0;
		for (int i = 0; i < str.length(); i++) {
			total += Integer.valueOf(Integer.parseInt(String.valueOf(str.charAt(i))));
		}
		return total;
	}
	
	public static void main(String[] args) {
		String cardNumber = "4992739871";
		System.out.println(getCheckNumber(cardNumber));
	}
}