不满意增值税编号检查数字算法



我编码了一个用于检查公司人格的增值税编号数字的函数。该功能起作用,但这很丑陋(太长又太复杂了)。

我是新的编程Python,想改善功能,因此我需要一些反馈和帮助。

增值税号码总是9位数字,首先是char,其余为数字。

char必须在letras字符串中。

最后一个数字是支票数字。

使用其他七个数字,算法是:

  1. 以次数为单位的数字。
  2. 奇数顺序的数字被乘以2(每个),如果每个结果的结果为> 10,则将单位添加到数十个中,然后四个结果被划分。
  3. 添加了步骤1和2中的小写。
  4. 获取单位,如果是0,则支票数字为0,在其他情况下为扣除10。结果是支票数字。

有效增值税号的一个示例是A58818501

代码

def validarCodigoCIF(entrada):
    """
    :param: entrada: str
    :rtype: bool
    """
    letras = "ABCDEFGHIJKLMNPQRSVW"
    if len(entrada) != 9 or entrada[0] not in letras:
        return False
    numero = entrada[1:10]
    pares = int(numero[1]) + int(numero[3]) + int(numero[5])
    impares = 0
    for i in range(0, 8, 2):
        j = int(numero[i]) * 2
        if j < 10:
            impares += j
        else:
            impares += j - 9
    digito = str(pares+impares)[-1]
    if int(digito) == 0:
        checkCIF = 0
    else:
        checkCIF = 10 - int(digito)
    # print(checkCIF)
    if str(checkCIF) == entrada[-1]:
        return True
    else:
        return False
entradaCodigoCIF = input('Enter the VAT number: ')
print(validarCodigoCIF(entradaCodigoCIF))

这是一个缩短版本

def check(vat_num):
    if len(vat_num) != 9 or vat_num[0] not in "ABCDEFGHIJKLMNPQRSVW":
        return False # trivial checks first
    nums = list(map(int, vat_num[1:8])) # numbers to check
    nums[1::2] = ((i * 2) - (9 if i > 4 else 0) for i in nums[1::2]) # alter odds
    return int(vat_num[8]) == (sum(nums) % 10) # compare to check digit

请注意以下有趣的*功能:

  1. 使用 [1::2]从峰值获取其他所有项目
  2. 使用map(int, ...)将相互关系中的所有项目转换为整数;和
  3. 使用% 10(Modulo)轻松获得数字的数字部分。

*可能不有趣

要解决的第一个问题是您的功能太长:

def calculate_pares(numero):
    return int(numero[1]) + int(numero[3]) + int(numero[5])
def calculate_impares(numero):
    result = 0
    for i in range(0, 8, 2):
        j = int(numero[i]) * 2
        if j < 10:
            result += j
        else:
            result += j - 9
    return result
def calculate_check_cif(entrada):
    numero = entrada[1:10]
    pares = calculate_pares(numero)
    impares = calculate_impares(numero)
    digito = str(pares+impares)[-1]
    if int(digito) == 0:
        return 0
    return 10 - int(digito)
def validarCodigoCIF(entrada):
    """
    :param: entrada: str
    :rtype: bool
    """
    letras = "ABCDEFGHIJKLMNPQRSVW"
    if len(entrada) != 9 or entrada[0] not in letras:
        return False
    checkCIF = calculate_check_cif(entrada)
    # print(checkCIF)
    return str(checkCIF) == entrada[-1]

这只是第一步,我认为您明白了。然后,当您拥有较小的功能时,进一步的改进会更容易。

另外,如果您用英语编写代码会更容易 - 那么人们可能会帮助您发现更多有意义的功能,而不是通过盲目分配/猜测。

查看增值税编号使用luhn checksum,我介绍了我最近在(未接受的)关于信用卡号码的答案中发布的修改版本。

该函数不一定比您的短,而是使用另一种方法:它在有效数字上返回None,而故障上的简短错误消息。它还确保了首字母后的数字有效,并允许空间和一些标点符号。

def invalid_cif_code(s):
    """ Returns None if s is a valid CIF code and a string 
        describing the error otherwise. The string may contain 
        spaces and punctuation, which is ignored.
    """
    # strip punctuation from string
    s = [x for x in s if x not in " t.-"]
    if len(s) != 9:
        return "Invalid length"
    if s[0] not in "ABCDEFGHIJKLMNPQRSVW":
        return "Invalid initial letter"
    # convert numerical part to list of digits
    try:
        code = [int(x) for x in s[1:]]
    except ValueError:
        return "Invalid non-digit in number"
    # multiply and cast out nines for every other codeit   
    for i in range(0, 8, 2):
        code[i] *= 2
        if code[i] > 9:
            code[i] -= 9
    # calculate checksum            
    s = (9 * sum(code)) % 10
    if s != 0:
        return "Invalid checksum"
    return None

典型的程序员对Luhn校验和使用更优雅的解决方案(尽管已应用于信用卡号并用JavaScript编写),该解决方案使用奇数数组的数组。

最新更新