How to validate and calculate the control digit of a CPF

1

How does the algorithm that calculates the digit of a CPF (Brazilian Physical Register) work? And how is this calculation used to validate the CPF? If possible, I would like examples in Python.

    
asked by anonymous 19.05.2015 / 01:57

3 answers

3

How does the algorithm that calculates the digit of a CPF (Brazilian Physical Register) work?

According to Wilson Neto's answer , there is an explanation in this link . Basically, Module 11 is applied to a 9-digit number to generate the first check digit. The second check digit is generated from the original 9 digits, plus the first check digit.

And how is this calculation used to validate the CPF?

The validation of the CPF is identical to the generation of the CPF. From the first 9 numbers, the two digits are generated. If they are the same as the input provided, the CPF is valid.

If possible, I would like examples in Python.

Here is the code for validating CPF in Python.

The original link is here .

#!/usr/bin/env python
#Djames Suhanko
import sys
try:
 cpflimpo=sys.argv[1]
except IndexError:
 print "Use %s NUMERO_DO_CPF" % sys.argv[0]
 sys.exit()

if (len(cpflimpo) != 11 or not cpflimpo.isdigit()):
 print "Formato errado. Tente de novo (apenas numeros)"
 sys.exit()

digito = {}
digito[0] = 0
digito[1] = 0
a=10
total=0
for c in range(0,2):
 for i in range(0,(8+c+1)):
  total=total+int(cpflimpo[i])*a
  a=a-1
 digito[c]=int(11-(total%11))
 a=11
 total=0
if (int(cpflimpo[9]) == int(digito[0]) and int(cpflimpo[10]) == int(digito[1])):
 print "CPF valido: ",
 for i in (range(len(cpflimpo))):
   if (i == 2 or i == 5):
    sep=cpflimpo[i]+" ."
   elif (i == 8):
    sep=cpflimpo[i]+" -"
   else:
    sep=cpflimpo[i]
   print "%s" % sep,
else:
 print "CPF invalido"
    
01.06.2015 / 17:23
2

Here is an example that can be used both on the command line and as a Python library, with doctests.

import re


def validar_cpf(cpf):
    """
    Retorna o CPF válido sanitizado ou False.

    # CPFs corretos
    >>> validar_cpf('123.456.789-09')
    '12345678909'
    >>> validar_cpf('98765432100')
    '98765432100'
    >>> validar_cpf(' 123 123 123 87 ')
    '12312312387'

    # CPFs incorretos
    >>> validar_cpf('12345678900')
    False
    >>> validar_cpf('1234567890')
    False
    >>> validar_cpf('')
    False
    >>> validar_cpf(None)
    False
    """
    cpf = ''.join(re.findall(r'\d', str(cpf)))

    if not cpf or len(cpf) < 11:
        return False

    antigo = [int(d) for d in cpf]

    # Gera CPF com novos dígitos verificadores e compara com CPF informado
    novo = antigo[:9]
    while len(novo) < 11:
        resto = sum([v * (len(novo) + 1 - i) for i, v in enumerate(novo)]) % 11

        digito_verificador = 0 if resto <= 1 else 11 - resto

        novo.append(digito_verificador)

    if novo == antigo:
        return cpf

    return False


if __name__ == "__main__":
    import sys

    if len(sys.argv) != 2:
        print("Uso: {} [CPF]".format(sys.argv[0]))
    else:
        cpf = validar_cpf(sys.argv[1])
        print(cpf if cpf else "CPF Inválido")
    
27.04.2018 / 23:37
0

One more solution would be:

pythonica

def validar_cpf(cpf: str) -> bool:

    """ Efetua a validação do CPF, tanto formatação quando dígito verificadores.

    Parâmetros:
        cpf (str): CPF a ser validado

    Retorno:
        bool:
            - Falso, quando o CPF não possuir o formato 999.999.999-99;
            - Falso, quando o CPF não possuir 11 caracteres numéricos;
            - Falso, quando os dígitos verificadores forem inválidos;
            - Verdadeiro, caso contrário.

    Exemplos:

    >>> validate('529.982.247-25')
    True
    >>> validate('52998224725')
    False
    >>> validate('111.111.111-11')
    False
    """

    # Verifica a formatação do CPF
    if not re.match(r'\d{3}\.\d{3}\.\d{3}-\d{2}', cpf):
        return False

    # Obtém apenas os números do CPF, ignorando pontuações
    numbers = [int(digit) for digit in cpf if digit.isdigit()]

    # Verifica se o CPF possui 11 números:
    if len(numbers) != 11:
        return False

    # Validação do primeiro dígito verificador:
    sum_of_products = sum(a*b for a, b in zip(numbers[0:9], range(10, 1, -1)))
    expected_digit = (sum_of_products * 10 % 11) % 10
    if numbers[9] != expected_digit:
        return False

    # Validação do segundo dígito verificador:
    sum_of_products = sum(a*b for a, b in zip(numbers[0:10], range(11, 1, -1)))
    expected_digit = (sum_of_products * 10 % 11) % 10
    if numbers[10] != expected_digit:
        return False

    return True

The implemented logic is exactly the same as that described in the other answers, but uses language tools to simplify the solution.

    
28.06.2018 / 14:22