5

您好,我正在尝试在 python 中创建一个函数来生成有效的 IMEI 号码,所以这是我的函数。IMEI 验证使用 Luhn 算法,所以我试图在我的脚本中实现它。

def getImei():
    num = ''
    suma = 0
    for i in range(0,13):
        digit = random.randrange(0,9)
        suma = suma + digit
        num = num + str(digit)

    suma = suma * 9
    digit = suma % 10
    num = num + str(digit)
    return num

但是,该功能无法生成有效的 IMEI 号码。我在维基百科上找到了一篇文章,告诉我如何生成校验位(http://en.wikipedia.org/wiki/Luhn_algorithm

校验位 (x) 是通过计算数字总和然后计算该值的 9 倍模 10 获得的(在等式形式中,(67 * 9 mod 10))。算法形式: 1.计算数字的总和(67)。2.乘以 9 (603)。3.最后一位,3,是校验位。

我错过了什么还是维基错了?

4

3 回答 3

7

请注意,奇数(从末尾开始,从 0 开始)位置的数字加倍,因此您必须将其添加到您的代码中,例如以下代码将返回 luhn 校验和:

def luhn_residue(digits):
    return sum(sum(divmod(int(d)*(1 + i%2), 10))
                 for i, d in enumerate(digits[::-1])) % 10

这里(1 + i%2)乘数等于2奇数定位数和偶数定位数1。然后sum(divmod(..., 10))返回(可能)两位数的数字总和,外部总和对结果序列求和。

您可以使用它来生成有效的数字序列:

def getImei(N):
    part = ''.join(str(random.randrange(0,9)) for _ in range(N-1))
    res = luhn_residue('{}{}'.format(part, 0))
    return '{}{}'.format(part, -res%10)

演示:

>>> luhn_residue('79927398713')
0
>>> luhn_residue('05671564547361')
6
>>> luhn_residue(getImei(14))
0
于 2013-12-22T19:43:08.403 回答
1

如果结果大于 10,您将跳过将每隔一个数字加倍并取它们的总和的步骤。来自Wikipedia

从最右边的数字(即校验位)开始,向左移动,每第二位的值加倍;如果这个加倍运算的乘积大于 9(例如,7 * 2 = 14),则将乘积的数字相加(例如,10:1 + 0 = 1、14:1 + 4 = 5)。

于 2013-12-22T19:42:58.913 回答
0

@alko 的解决方案不适用于所有 IMEI 号码:请参阅有效 imei 号码列表(或 cc 号码,实际上是相同的)。

这是有效的解决方案:

def luhn_residue(digits):
    """ Lunh10 residue value """
    s = sum(d if (n % 2 == 1) else (0, 2, 4, 6, 8, 1, 3, 5, 7, 9)[d]
            for n, d in enumerate(map(int, reversed(digits))))
    return (10 - s % 10) % 10
于 2014-02-15T02:19:25.227 回答