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.
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.
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.
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.
Here is the code for validating CPF in Python.
#!/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"
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")
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.