
Modulus 11 (mod11) é um algoritmo para criar um dígito de verificação baseado numa sequência de números pré determinada. Ele é bastante parecido com o Algoritmo de Luhn, com a diferença de que usa pesos para multiplicar cada dígito da sequência. Estes pesos variam de 2 a n, onde n pode variar de aplicação para aplicação.
Diferentemente do algoritmo de Luhn, é difícil encontrar informações precisas sobre o mod11 e suas implementações variam bastante de programador para programador. Uma boa implementação que eu encontrei, foi a da HP:
Diferentemente do algoritmo de Luhn, é difícil encontrar informações precisas sobre o mod11 e suas implementações variam bastante de programador para programador. Uma boa implementação que eu encontrei, foi a da HP:
- Tome uma sequência de números.
- Começando da última posição, multiplique o item por 2 e adicione o resultado ao somatório, que deve iniciar com 0.
- Repita o passo 2 para os outros itens da sequência, lembrando de incrementar em 1 o fator multiplicador (quando este for maior que o valor máximo de multiplicação, deve ser reiniciado com o valor 2).
- Divida o somatório por 11 e considere o resto da divisão.
- Subtraia de 11, o valor obtido no passo 4 e o resultado será o dígito de verificação.
Apesar de parecer perfeito à primeira vista, o algoritmo apresentado possui duas falhas. Caso o resultado do passo 4 for 0 ou 1, o resultado do passo 5 será 11 ou 10, respectivamente. Isto contraria a idéia do dígito de verificação ser um número entre 0 e 9.
Segundo a implementação da HP, um resultado 10 significa que a sequência de números é inválida para utilização com o algoritmo. Já um resultado 11 implica que a saída do algoritmo é 0. Seria relativamente fácil implementar esta solução, mas isto significaria que muitos números não poderiam ser usados com este algoritmo.
Para quem não sabe, muitos documentos brasileiros utilizam o mod11 para cálculo dos seus dígitos verificadores, como o CPF, CNPJ e Título de Eleitor, além de códigos mais diversos, como o código de procedimentos do SUS (Sistema Único de Saúde). Sendo assim, era preciso adaptar o algoritmo para trabalhar com qualquer saída, tratando-a.
A solução que eu encontrei foi:
- Tome uma sequência de números.
- Começando da última posição, multiplique o item por 2 e adicione o resultado ao somatório, que deve iniciar com 0.
- Repita o passo 2 para os outros itens da sequência, lembrando de incrementar em 1 o fator multiplicador (quando este for maior que o valor máximo de multiplicação, deve ser reiniciado com o valor 2).
- Subtraia de 11, o resto da divisão do somatório por 11.
- Se o resultado obtido no passo 4 for maior que 9, o dígito verificador será 0. Senão, o dígito verificador será o próprio resultado do passo 4.
Como pode ser percebido, a diferença do segundo, para o primeiro algoritmo apresentado é que, em vez de descartar uma sequência de números cujo dígito verificador dê 10, o segundo retorna o valor 0 para o mesmo. Isto garante que o mesmo funcionará para qualquer sequência de números.
Com a implementação do algoritmo mod11 como uma função separada, fica fácil calcular os dígitos verificadores de quaisquer documentos que o utilizem, tornando os códigos mais limpos e aumentando a reusabilidade de código. Para concluir, segue abaixo a implementação deste algoritmo feita por mim em Python.
# Modulus 11
#
# AUTHOR: Jose Lopes de Oliveira Junior
# http://versaopropria.blogspot.com
# jlojunior _at_ gmail _dot_ com
#
# DATE: 2008/10/27
#
# LICENCE: GPLv3 - http://www.gnu.org/licenses/gpl.html
#
# DESCRIPTION: Implements Modulus 11 check digit algorithm
# +as a function. See the docstring for more details.
def mod11(list, max_weight=7):
"""Implements Modulus 11 check digit algorithm.
It's a variation of the HP's Modulus 11 algorithm.
Requires the sequence to be calculated in a list of
integers.
The HP's Modulus 11 algorithm can be accessed through
the following link:
http://docs.hp.com/en/32209-90024/apds02.html
"""
sum = 0
weight = 2
# Iterates through the list from right to left,
# +multiplying each value for it's weight. If
# +the weight reaches max_weight, then it is
# +restarted to 2.
for item in reversed(list):
sum += item * weight
weight += 1
if weight > max_weight:
weight = 2
mod = 11 - sum % 11
# HP's Modulus 11 algorithm says that a 10
# +result is invalid and a 11 result is equal
# +to 0. So, both values are returned as 0.
if mod > 9:
return 0
else:
return mod
Código 1. Modulus 11 em Python.
Leia Também
- O Algoritmo de Luhn – Entenda o funcionamento e algumas aplicações deste famoso algoritmo para criação e checagem de dígitos de verificação.
- Calculando a Data da Páscoa em Python – Aprenda como são calculados os feriados móveis do ano.
- O Crivo de Eratóstenes em Python – Aprenda como funciona e veja um exemplo de implementação deste algoritmo em Python.
- Destrinchador de IPs em Java – Um Applet que obtém informações sobre um endereço IP e sua máscara.
Nenhum comentário:
Postar um comentário