LUHN是一个算法,它的就要作
用是为了计算信用卡等证件号码的
合法性。我们用一个例子来看一下
这个算法的工作过程:
假设我们有一个数4992 73 9871,这个数是没有带校验码
- 由最低位起每隔一位取一个数字,
将这个数字乘2;
1*2=2 8*2=16 3*2=6 2*2=4 9*2=18 - 将数字中余下的数字和上面结果中
的数字直接相加,得到结果B;
4 + 1+8 + 9 + 4 + 7 + 6 + 9 + 1+6 + 7 + 2 = 64 - 生成校验码C=A-B,其中A是
比B大的10倍数中最小的数字, 如B=86,则A=90;如B= 34,A=40;
6 = 70-64 - 将校验码加在原来数字的后面生成
合法的帐户密码;
4992 73 9871
现已Master Card为例:
- <script>
- function isValidMasterCard(sText){
- var reMasterCard=/^(5[1-5]/d{2})[/s/-]?(/d{4})[/s/-]?(/d{4})[/s/-](/d{4})$/;
- if(reMasterCard.test(sText)){
- var sCardNum=RegExp.$1+RegExp.$2+RegExp.$3+RegExp.$4;
- alert(sCardNum);
- //Luhn algorithm here
- return luhnCheckSum(sCardNum);
- }else{
- return
- }
- }
- function luhnCheckSum(sCardNum){
- var iOddSum=0;
- var iEvenSum=0;
- var bIsOdd=true;
- for(var i=sCardNum.length-1;i>=0;i--){
- //alert("length="+sCardNum.length);
- //alert("sCardNum.char("+i+")="+sCardNum.charAt(i));
- var iNum=parseInt(sCardNum.charAt(i));
- if(bIsOdd){
- //反向奇數求和
- iOddSum+=iNum;
- }else{
- //偶數
- if(iNum>9){
- iNum=eval(iNum.toString().split("").join("+"));
- }
- iEvenSum+=iNum;
- }
- bIsOdd=!bIsOdd;
- }
- return ((iEvenSum+iOddSum)%10==0);
- }
- alert(isValidMasterCard("5432 1234 5678 9012"));
- alert(isValidMasterCard("5432-1234-5678-9012"));
- </script>
C++例子:
LLUHN.cpp
- //
- //
- // Designed by Liutao, Xi'an Jitotong University
- // 2001-04-23
- //
- //
- //
- // LLUHN.cpp: implementation of the LLUHN class.
- //
- //
- #include "LLUHN.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- //
- // Construction/Destruction
- //
- LLUHN::LLUHN()
- {
- m_strCardNum = _T("");
- }
- LLUHN::LLUHN(CString strCardNum)
- {
- for (int i=0; i<strCardNum.GetLength(); i++)
- if (!isdigit(strCardNum[i]))
- {
- LLUHN();
- return;
- }
- m_strCardNum = strCardNum;
- }
- LLUHN::~LLUHN()
- {
- m_strCardNum = _T("");
- }
- #define CurrentDigit(i) (m_strCardNum[i]-'0')
- BOOL LLUHN::IsValid()
- {
- int sum = 0;
- if (m_strCardNum.IsEmpty()) return false;
- for (int i=m_strCardNum.GetLength()-2; i>=0; )
- {
- sum += CurrentDigit(i)*2>10 ? 1+(CurrentDigit(i)*2)%10 : CurrentDigit(i)*2, i--;
- if (i>=0) sum += CurrentDigit(i), i--;
- }
- return (10-sum%10)==(m_strCardNum[m_strCardNum.GetLength()-1]-'0');
- }
- char LLUHN::GetCheckSum()
- {
- int sum = 0;
- if (m_strCardNum.IsEmpty()) return false;
- for (int i=m_strCardNum.GetLength()-1; i>=0; )
- {
- sum += CurrentDigit(i)*2>10 ? 1+(CurrentDigit(i)*2)%10 : CurrentDigit(i)*2, i--;
- if (i>=0) sum += CurrentDigit(i), i--;
- }
- return (10-sum%10+'0');
- }
- #undef CurrentDigit
- BOOL LLUHN::SetCardNum(CString strCardNum)
- {
- for (int i=0; i<strCardNum.GetLength(); i++)
- if (!isdigit(strCardNum[i])) return false;
- m_strCardNum = strCardNum;
- return true;
- }
- const CString LLUHN::GetCardNum()
- {
- return m_strCardNum;
- }
LLUHN.h
- //
- //
- // Designed by Liutao, Xi'an Jitotong University
- // 2001-04-23
- //
- //
- //
- // LLUHN.h: interface for the LLUHN class.
- //
- //
- #if !defined(AFX_LLUHN_H__6ACE3589_24B6_466C_921F_DCA4CA09AC97__INCLUDED_)
- #define AFX_LLUHN_H__6ACE3589_24B6_466C_921F_DCA4CA09AC97__INCLUDED_
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- class LLUHN
- {
- public:
- const CString GetCardNum();
- char GetCheckSum();
- BOOL IsValid();
- BOOL SetCardNum(CString strCardNum);
- LLUHN();
- LLUHN(CString strCardNum);
- virtual ~LLUHN();
- private:
- CString m_strCardNum;
- };
- #endif // !defined(AFX_LLUHN_H__6ACE3589_24B6_466C_921F_DCA4CA09AC97__INCLUDED_)
参考资料:见 Luhn algorithm http://en.wikipedia.org/wiki/Luhn_algorithm