银行卡卡号检测Luhn算法 Objective-C实现
Luhn 算法简介
Luhn 算法或是Luhn 公式,也被称作“模10算法”。它是一种简单的校验公式,一般会被用于身份证号码,IMEI号码,美国供应商识别号码,或是加拿大的社会保险号码的验证。该算法是由IBM的科学家Hans Peter Luhn所创造,于1954年1月6日提出该专利的申请,并于1960年8月23日被授予,在美国的专利号为2950048。
该算法一直都被大家所公用,并且时至今日应用也很广泛。它被指定在ISO/IEC7812-1。它的目的不是成为一种加密安全的哈希函数;它的目的是防止意外出现的错误,而不是恶意攻击。很多信用卡和众多的政府身份识别号码都使用该算法从一系列的随机数字中提取有效的数字。
优点和缺点
Luhn 算法会检测到任何单码的错误以及几乎所有的相邻数字换位的错误。但是它不会检测两个数字序列09转90的错误(反之亦然)。它会检测到十分之七的相同双位数错误(不会检测到22和55的互换,33和66的互换,44和77的互换)。其他更复杂的检查数字算法,如费尔赫夫算法,可以检测出更多的转录错误。模N的Luhn算法是Luhn算法的一个扩展,支持非数字字符串。因为该算法采取了从右向左的方式,而且零位会影响计算的结果。只有当零位造成了数位的移动或是用零来填充一串数字的开头时才不会影响计算结果的生成。因此不论在将1234用零填充为0001234之前或是之后,使用Luhn算法得到的结果都是一样的。
该算法在美国专利上是为了给手持或是机械设备计算校验码。所以它必须尽可能的简单。
算法描述
- 从卡号最后一位数字开始,偶数位乘以2,如果乘以2的结果是两位数,将结果个位和十位相加,或者直接减去9。
- 把所有数字相加,得到总和。
- 如果信用卡号码是合法的,总和可以被10整除。
OC实现
/**
* 匹配Luhn算法:可用于检测银行卡卡号
* @param cardNo
* @return
*/
+(BOOL)isMatchLuhn:(NSString*)cardNo {
cardNo = [cardNo stringByReplacingOccurrencesOfString:@" " withString:@""];
/* 步骤1
按照从右往左的顺序,从这串数字的右边开始,包含校验码,将偶数位数字乘以2,
如果每次乘二操作的结果大于9(如 8 × 2 = 16),然后计算个位和十位数字的和
(如 1 + 6 = 7)或者用这个结果减去9(如 16 - 9 = 7) */
NSMutableArray* newNumArray = [NSMutableArray array];
NSString* cardNoChar = nil;
for(long i = cardNo.length - 2; i >= 0; i -= 2)
{
// 奇数位
cardNoChar = [cardNo substringWithRange:NSMakeRange(i + 1, 1)];
[newNumArray addObject:cardNoChar];
// 偶数位
cardNoChar = [cardNo substringWithRange:NSMakeRange(i, 1)];
int k = [cardNoChar intValue]*2;
// 处理大于9的情况
k = k % 10 + k / 10;
[newNumArray addObject:[NSString stringWithFormat:@"%d", k]];
if (i == 1) {
// 奇数位
cardNoChar = [cardNo substringWithRange:NSMakeRange(i - 1, 1)];
[newNumArray addObject:cardNoChar];
}
}
/* 步骤2 第一步操作过后会得到新的一串数字,计算所有数字的和(包含校验码) */
int sum = [[newNumArray valueForKeyPath:@"@sum.integerValue"] intValue];
/* 步骤3 用第二步操作得到的和进行“模10”运算,如果结果位0,表示校验通过,否则失败 */
return sum % 10 == 0;
}