Validação do número de registro de CNH
06/03/2008
0
Já pesquisei em tudo que é forum e não encontrei uma solução definitiva para o cálculo dos Dígitos Verificadores do Registro de CNH.
O número tem 11 dígitos e os 2 últimos são os DV.
Peguei algumas idéias mas não atendem 100¬ dos números, principalmente os que terminam em ´00´.
Se alguem puder dar uma ajuda, ficarei grato.
Cps.art
Post mais votado
27/03/2013
FUNCTION VRegCnh(PVRegCnh : string) : string; stdcall;
var
j, Mult, Soma, Digito1, Digito2, Incr_dig2: integer;
CNH_Forn, Dig_Forn, Dig_Enc : string;
begin
Result := F;
if length(Trim(PVRegCnh)) < 11 then
Exit;
CNH_Forn := Copy(PVRegCnh,1,9);
Dig_Forn := Copy(PVRegCnh,10,2);
Incr_Dig2 := 0;
Soma := 0;
Mult := 9;
for j := 1 to 9 do
begin
Soma := Soma + (StrToInt(CNH_Forn[j]) * Mult);
Mult := Mult - 1;
end;
Digito1 := Soma Mod 11;
if Digito1 = 10 then
begin
Incr_Dig2 := - 2;
end;
if Digito1 > 9 then
begin
Digito1 := 0;
end;
Soma := 0;
Mult := 1;
for j := 1 to 9 do
begin
Soma := Soma + (StrToInt(CNH_Forn[j]) * Mult);
Mult := Mult + 1;
end;
if (Soma Mod 11) + Incr_Dig2 < 0 then
begin
Digito2 := 11 + (Soma Mod 11) + Incr_Dig2;
end;
if (Soma Mod 11) + Incr_Dig2 >= 0 then
begin
Digito2 := (Soma Mod 11) + Incr_Dig2;
end;
if Digito2 > 9 then
begin
Digito2 := 0;
end;
Dig_Enc := IntToStr(Digito1)+IntToStr(Digito2);
if Dig_Forn = Dig_enc then
begin
Result := V;
end;
if Dig_Forn Dig_enc then
begin
Result := F;
end;
end;
Clovis Perazza
Mais Posts
14/08/2009
Provisorio
Quero agradecer por postar a única solução que realmente funciona para todos os CNHs!
PARABÉNS por desenvolver o único algoritmo que desvendou o cálculo do DV da CNH! Esse algoritmo não foi divulgado e você foi o único que realmente o desvendou!
Valeu pela força! Agora, os milhares de CNHs estão validando 100¬!
Obrigado!
Abraços e sucesso!
01/02/2012
Rafael Fig
Estava a procura de como validar a CNH, encontrei esse tópico que parece ter achado uma solução funcional.
cps.art, poderia publicar a explicação da solução? Como um algoritmo ou solução descritiva para que seja possível qualquer pessoa implementar em outras linguagens.
É validação Módulo 11 com alguma característica particular?
Grato!.
12/05/2012
Ailtonfinan
Essa função que postei aqui é para validar CNHs novas, de 11 dígitos, ou seja, 9 dígitos + 2 verificadores. Ex: 123.456.789-01.
Para validar as CNHs antigas, as chamadas PGU, de 8 dígitos mais 1 DV, o algoritimo é diferente.
Fiz uma correção na função que postei anteriormente, então fica assim:
[b:8147beb8c0]FUNCTION VRegCnh(PVRegCnh : string) : string; stdcall;
var
j, Soma, Digito1, Digito2, Incr_dig2: integer;
CNH_Forn, Dig_Forn, Dig_Enc : string;
begin
Result := ´F´;
if length(Trim(PVRegCnh)) < 11 then
Exit;
CNH_Forn := Copy(PVRegCnh,1,9);
Dig_Forn := Copy(PVRegCnh,10,2);
Incr_Dig2 := 0;
// calcula o digito 1 (10º caractere)
Soma := 0;
for j := 9 downto 1 do
Soma := Soma + ( StrToInt(CNH_Forn[j]) * (10-j));
Digito1 := Soma Mod 11;
if Digito1 >= 10 then
begin
Incr_Dig2 := -2; // Aqui está o segredo
Digito1 := 0;
end;
// calcula o digito 2 (11º caractere)
Soma := 0;
for j := 9 downto 1 do
Soma := Soma + ( StrToInt(CNH_Forn[j]) * (j));
Digito2 := (Soma Mod 11) + Incr_Dig2; // [color=red:8147beb8c0]soma o incremento aqui[/color:8147beb8c0]
if Digito2 >= 10 then
begin
Digito2 := 0;
end;
// Digito2 := Digito2 + Incr_Dig2; // [color=red:8147beb8c0]tira esta linha[/color:8147beb8c0]
Dig_Enc := IntToStr(Digito1)+IntToStr(Digito2);
if Dig_Forn = Dig_enc then
begin
Result := ´V´;
end;
if Dig_Forn Dig_enc then
begin
Result := ´F´;
end;
end;[/b:8147beb8c0]
Essa alteração é por que o segundo dígito poderia ser tambem maior que 9, o que faria ele ser ´0´ (zero), e se o primeiro tambem tivesse sido maior que 9, o incremento seria -2, então o segundo seria ´0-2=-2´ o que seria incorreto.
Vou passar a função para validar CNHs antigas, na próxima mensagem.
fale amigo blz me chamo ailton
saber nao sou progamador igual há vcs minha funçao e outra mas interecei na area que vcs exercem estou aki nao pra da opiniao mas sim pra gente ganha dinheiro se intereca a vc entre em contato nesse mesmo endereço pop.ailton@hotmail.com
esse tambem e meu msn blz aguardo resposta de vc abraço. e muito simples e facio. geralmente ou quase o dia todo on line pelo msn ok.
12/05/2012
Ailtonfinan
http://delphiforall.blogspot.com/2008/09/algortimo-para-validao-de-cnh.html
fale amigo blz me chamo ailton
saber nao sou progamador igual há vcs minha funçao e outra mas interecei na area que vcs exercem estou aki nao pra da opiniao mas sim pra gente ganha dinheiro se intereca a vc entre em contato nesse mesmo endereço pop.ailton@hotmail.com
esse tambem e meu msn blz aguardo resposta de vc abraço. e muito simples e facio. geralmente ou quase o dia todo on line pelo msn ok.
12/05/2012
Ailtonfinan
18. CÓDIGO NUMÉRICO DE VALIDAÇÃO: com 11 (onze) dígitos gerados a partir de algoritmo específico e de propriedade do DENATRAN, composto pelos dados individuais de cada CNH, permitindo a validação do documento;
=============================================
Art. 2º. O documento de Habilitação terá 2 (dois) números de identificação nacional e 1 (um) número de identificação estadual, que são:
I – o primeiro número de identificação nacional – Registro Nacional, será gerado pelo sistema informatizado da Base Índice Nacional de Condutores – BINCO, composto de 9 (nove) caracteres mais 2 (dois) dígitos verificadores de segurança, sendo único para cada condutor e o acompanhará durante toda a sua existência como condutor, não sendo permitida a sua reutilização para outro condutor.
fale amigo blz me chamo ailton
saber nao sou progamador igual há vcs minha funçao e outra mas interecei na area que vcs exercem estou aki nao pra da opiniao mas sim pra gente ganha dinheiro se intereca a vc entre em contato nesse mesmo endereço pop.ailton@hotmail.com
esse tambem e meu msn blz aguardo resposta de vc abraço. e muito simples e facio. geralmente ou quase o dia todo on line pelo msn ok.
II – [b:222657da1c]o segundo número de identificação nacional – Número do Espelho da CNH, será formado por 8 (oito) caracteres mais 1 (um) dígito verificador de segurança, autorizado e controlado pelo órgão máximo executivo de trânsito da União, e identificará cada espelho de CNH expedida.[/b:222657da1c]
a) [b:222657da1c]O dígito verificador será calculado pela rotina denominada de “módulo 11” e sempre que o resto da divisão for zero (0) ou um (1), o dígito verificador será zero (0); [/b:222657da1c]
III – o número de identificação estadual será o número do formulário RENACH, documento de coleta de dados do candidato/condutor gerado a cada serviço, composto, [b:222657da1c]obrigatoriamente, por 11 (onze) caracteres, sendo as duas primeiras posições formadas pela sigla da Unidade de Federação expedidora, facultada a utilização da última posição como dígito verificador de segurança.[/b:222657da1c]
12/05/2012
Ailtonfinan
Mas não funciona para todos os números.
Tem número de registro de CNH com dígito 1 (um), então se aplicarmos:
[code:1:f3064a86dd]Conta := (Soma div 11) * 11;
if (Soma - Conta) < 2 then
Dv := 0
else
Dv := 11 - (Soma - Conta);[/code:1:f3064a86dd]
já percebe-se que nunca vai se encontrar o dígito 1.
Vamos continuar tentando.[/quote:f
NUNCA VAI ENCONTRAR O DÍGITO 1 ?????
sua afirmação está equivocada.
vamos utilzar uma variável para ilustrar melhor:
[code:1:f3064a86dd]Conta := (Soma div 11) * 11;
DVx := Soma - Conta;
if DVx < 2 then
Dv := 0
else
Dv := 11 - DVx;[/code:1:f3064a86dd]
não há qualquer alteração no código, exceto a atribuição da variável, certo? então...
se DVx resultou em 0 ou 1, Dv será 0.
se DVx resultou em 5, então Dv será 6.
se DVx resultou em 10, qual será o valor de Dv??? tchanammmm.... 1 !!!
de qualquer modo, pulblique alguns números de CNH que você não conseguiu validar com os algoritmos que você encontrou.
fale amigo blz me chamo ailton
saber nao sou progamador igual há vcs minha funçao e outra mas interecei na area que vcs exercem estou aki nao pra da opiniao mas sim pra gente ganha dinheiro se intereca a vc entre em contato nesse mesmo endereço pop.ailton@hotmail.com
esse tambem e meu msn blz aguardo resposta de vc abraço. e muito simples e facio. geralmente ou quase o dia todo on line pelo msn ok.
12/05/2012
Ailtonfinan
Digo ´quase´, pois num laço de repetição que testei uma massa de 3123 números de CNH, apenas 90 não validaram por esta função. Porém estas 90 são CNHs válidas, como pode ser verificado em sites do DETRAN.
Exemplos de CNHs válidas (que não validaram com essa função) são:
112274500 - 113473508 - 115478700 - 134934008 - 138273900 - 138876109 - 186499700 - 218659309 - 219077908 - 241595908 - 293766109 - 293821800 - 301823609 - 307412830 - 308041097 - 308510968 - 308601149 - 308656679 - 309493455 - 309508711 - 309626331 - 310376408 - 313736375 - 314019286 - 314035249 - 315040424 - 315097256 - 315259515 - 315323140 - 315558600 - 316629073 - 317775758 - 318109778 - 318490102 - 318494361 - 327244208 - 330157409 - 374723809 - 413981908 - 416345009 - 530678608 - 679221808 - 697159700 - 709245709 - 715334009 - 804310709 - 869586408 - 894476709
Para conseguir a lista com as 3123 CNHs, basta acessar
http://www.detran.rj.gov.br/_monta_aplicacoes.asp?doc=5646&cod=14&tipo=exibe_noticias&pag_noticias=true
E para testar o dígito verificador oficialmente pelo Detran, podemos usar o link https://wwws.detrannet.mg.gov.br/detran/pontuacond.asp?IdServico=36
Verifiquem. Estou tentando achar qual é o erro. De qualquer maneira, o algoritmo é muito bom, e valida na grande maioria dos casos (apenas 3¬ de erro), porém meio erro ainda é um erro.
Vamos tentar achar um algoritmo que valide 100¬ dos números que passei?
Abraços a todos!
fale amigo blz me chamo ailton
saber nao sou progamador igual há vcs minha funçao e outra mas interecei na area que vcs exercem estou aki nao pra da opiniao mas sim pra gente ganha dinheiro se intereca a vc entre em contato nesse mesmo endereço pop.ailton@hotmail.com
esse tambem e meu msn blz aguardo resposta de vc abraço. e muito simples e facio. geralmente ou quase o dia todo on line pelo msn ok.
07/01/2013
Roger Bifarat
07/01/2013
Roger Bifarat
10/03/2013
Luciano Chima
27/03/2013
Marcelo Freitas
function VRegCnh(PVRegCnh) { var Soma, Digito1, Digito2, Incr_dig2; //: integer; var CNH_Forn, Dig_Forn, Dig_Enc;// : string; if (PVRegCnh.length != 11) return CNH_Forn = PVRegCnh.slice(0,9); Dig_Forn = PVRegCnh.slice(9); Incr_Dig2 = 0; // calcula o digito 1 (10º caractere) Soma = 0; Mult = 9; for(j=1;j 9) { Digito1 = 0; } // calcula o digito 2 (11º caractere) Soma = 0; Mult = 1; for (j=1; j= 10) { Digito2 = 0; } //alert("PVRegCnh:"+PVRegCnh+" | CNH_Forn:"+CNH_Forn+" | Dig_Forn:"+Dig_Forn+" | Digito1:"+Digito1+" | Digito2:"+Digito2); if (Digito1 != PVRegCnh[9] || Digito2 != PVRegCnh[10]) {return "V";}//alert("A CNH está incorreta!\n\nOs dígitos verificadores são inválidos!");} else return "F"; }
Desculpa por responder isso na sala de Delphi, mas acho que o tópico tem mais a ver com a validação que com a linguagem.
27/03/2013
Clovis Perazza
Veja abaixo se essa função te ajuda.
FUNCTION VMod110(PVMod110 : string) : string;
var
LenPVMod110 : integer;
MultVMod110 : integer;
SomaVMod110 : integer;
PVMod110New : string;
PVMod110Dig : string;
kvm : integer;
DigMod110 : string;
begin
MultVMod110 := 9;
SomaVMod110 := 0;
PVMod110 := trim(PVMod110);
LenPVMod110 := length(PVMod110);
PVMod110New := Copy(PVMod110,1,LenPVMod110 - 1);
PVMod110Dig := Copy(PVMod110,LenPVMod110,1);
if LenPVMod110 < 2 then
begin
Result := F;
Exit;
end;
if StrToInt(PVMod110New) < 1 then
begin
Result := F;
Exit;
end;
for kvm := LenPVMod110 - 1 downto 1 do
begin
SomaVMod110 := SomaVMod110 + (MultVMod110 * StrToInt(Copy(PVMod110New,kvm,1)));
MultVMod110 := MultVMod110 - 1;
if MultVMod110 = 1 then
begin
MultVMod110 := 9
end;
end;
DigMod110 := IntToStr(SomaVMod110 mod 11);
if DigMod110 = 10 then
begin
DigMod110 := 0
end;
PVMod110New := PVMod110New + DigMod110;
if PVMod110 = PVMod110New then
Result := V
else begin
Result := F
end;
end;
22/10/2014
Jfpimentel
Obrigado
22/10/2014
Clovis Perazza
O número é 026418081 e o DV é 40 o que é validado pela função que está neste post.
Essa função valida o número inteiro, ou seja, você fornece o número 02641808140 e a função checa se a CNH 026418081 tem mesmo o DV 40.
Espero ter ajudado.
26/11/2014
George Lopes
Primeiramente gostaria de agradecer ao Sr. Clovis Perazza, pela contribuição!
Desculpem postar em um tópico antigo... mas acredito que possa ser útil para quem desenvolve em PHP, especialmente no framework Yii.
Usando o mesmo algoritmo de validação para CNH de 11 dígitos, criei um validador para Yii, não fiz muitos testes, mas funcionou com os que já realizei.
O código segue abaixo:
<?php class cnh extends CValidator { /** * Validates the attribute of the object. * If there is any error, the error message is added to the object. * @param CModel the data object being validated * @param string the name of the attribute to be validated. */ protected function validateAttribute($object, $attribute) { if (!$this->validaCnh($object->$attribute)) { $this->addError($object, $attribute, Yii::t('yii', ' não é um número válido.')); } } // Função que valida o número da CNH private function validaCnh($pvRegCnh) { // Verifiva se o número digitado contém todos os digitos $result = false; if (strlen(trim($pvRegCnh)) < 11) { // Caso tenha menos de 11 dígitos return false; } $cnh_forn = substr($pvRegCnh, 0, 9); // Deixa dois dígitos de fora $dig_forn = substr($pvRegCnh, 9, 2); $incr_dig2 = 0; $soma = 0; $mult = 9; for ($j = 0; $j < 9; $j++) { $soma = $soma + (intval(substr($cnh_forn, $j, 1)) * $mult); $mult = $mult - 1; } $digito1 = $soma % 11; if ($digito1 == 10) { $incr_dig2 = -2; } if ($digito1 > 9) { $digito1 = 0; } $soma = 0; $mult = 1; for ($j = 0; $j < 9; $j++) { $soma = $soma + (intval(substr($cnh_forn, $j, 1)) * $mult); $mult = $mult + 1; } if ((($soma % 11) * $incr_dig2) < 0) { $digito2 = 11 + ($soma % 11) + $incr_dig2; } if ((($soma % 11) + $incr_dig2) >= 0) { $digito2 = ($soma % 11) + $incr_dig2; } if ($digito2 > 9) { $digito2 = 0; } $dig_enc = strval($digito1) + strval($digito2); if ($dig_forn == $dig_enc) { return true; } else { return false; } } }
Clique aqui para fazer login e interagir na Comunidade :)