Validação do número de registro de CNH
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
Melhor post

Clovis Perazza
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;
Mais Respostas

Onjahyr
06/03/2008
Se puder enviar e-mails também poderemos unir as forças (envie para diversos estados, pois se um não souber o outro pode saber)...
Blz.

Cps.art
06/03/2008
Vou tentar, se conseguir alguma coisa coloco aqui neste tópico.

Asales
06/03/2008
Você já tem a função ou parte da função pronta para testar? Se tiver poste aqui.
Para quem se interessar este é o link para download do documento que regulamenta o documento de cnh:
http://www.denatran.gov.br/download/Resolucoes/resolucao_192_06.doc

Onjahyr
06/03/2008
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.
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]

Cps.art
06/03/2008
Não montei a função ainda, só estou fazendo testes no Excel para descobrir a forma de calcular esses DVs.
A CNH tem 2 números, 1 em preto, na vertical do lado esquerdo da foto e no verso do lado esquerdo da assinatura do delegado, e é chamdo de ´ESPELHO´, o outro fica abaixo da foto, em vermelho e é chamado de ´REGISTRO´.
O primeiro tem 8 dígitos e um DV, e a informação da letra a) da Res. do Denatran ([b:25f0df1472]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:25f0df1472]), tambem está furada para o DV do espelho, pois tem espelho com DV 1, o que não poderia acontecer.
Já o segundo número, o REGISTRO, que tem 2 DVs, na maioria dos casos consegui uma forma de validar, porem, para os números que tem DVs ´00´, a mesma regra não se aplica, e para DVs ´01, 02, 03....09´, em alguns casos tambem não.
Trabalho no Detran aqui na minha cidade e cuido do setor de CNH.
Estou tentando montar um sisteminha de protocolo digital para a agencia do Detran aqui da minha cidade, e um para as Auto-Escolas pra agendamento de Provas (Teórica e Prática) para evitar excesso de digitação desnecessária, ou seja, elas me passariam o agendamento em disquetes, e eu compilaria tudo num BD para controle de aprovações e de novos agendamentos, e para isso eu preciso que os números de REGISTRO, assim como CPF e RENACH, fossem validados na digitação para evitar erros.
O CPF e o RENACH não tem problema, mas esse do REGISTRO não há meio de descobrir.
O Denatran não fornece o algorítimo, e não sei porque fazem tanto segredo, se a própria RECEITA FEDERAL forneceu o do DV do CPF e CGC.
Fica então a nosso cargo descobrir isso, mesmo que seja pra auxiliar no próprio serviço do Detran.
Não dá pra entender o que se passa na cabeça desse povo.
Mas vamos tentando que descobriremos.
Abraços.

Asales
06/03/2008
já que vc está utilizando o Excel vc viu este post no link abaixo?
Ele traz duas funções em VBA para validação dos números presentes na CNH.
Se funcionar poste aqui porque fica mais fácil convertê-los para Pascal.
http://forumaccess.com/eve/forums/a/tpc/f/273606921/m/8751053512

Cps.art
06/03/2008
Já tinha visto esse forum sim.
Já testei o algoritimo que o Mc Feba utiliza e acontece o que eu disse acima, os DVs terminados em ´[b:d87629c409]00[/b:d87629c409]´ não validam, assim como alguns terminados em ´[b:d87629c409]01, 02......08, 09[/b:d87629c409]´.
Na função dele, quando o [b:d87629c409]Resto = 0 ou Resto = 1, o Resto será 0[/b:d87629c409].
Só isso já invalida o algorítimo, pois tem numeros que tem o último dígito igual a [b:d87629c409]1[/b:d87629c409].
Vamos continuar tentando.
Abraços.

Cps.art
06/03/2008
Nada ainda?
Até hoje não consegui nada.
O próprio Detran nem responde meus emails.
Cambada de safados!!!!
Acho que o chefe do Detran do estado de São Paulo não sabe nem o que é CNH.
Se falarem a sigla CNH pra ele, é capaz de pensar que é alguma doença contagiosa, imaginem se ele vai saber o que é ´algoritimo para cálculo de DV de CNH´.
Vai achar que é alguma organização terrorista.
Essas instituições do estado são uma merda mesmo.
Mas vou continuar tentando.
Abraços.

José Henrique
06/03/2008
http://delphiforall.blogspot.com/2008/09/algortimo-para-validao-de-cnh.html

Cps.art
06/03/2008
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:
[b:d9a37c2f07]Conta := (Soma div 11) * 11;
if (Soma - Conta) < 2 then
Dv := 0
else
Dv := 11 - (Soma - Conta);[/b:d9a37c2f07]
já percebe-se que nunca vai se encontrar o dígito 1.
Vamos continuar tentando.

Emerson Nascimento
06/03/2008
Conta := (Soma div 11) * 11; if (Soma - Conta) < 2 then Dv := 0 else Dv := 11 - (Soma - Conta);
NUNCA VAI ENCONTRAR O DÍGITO 1 ?????
sua afirmação está equivocada.
vamos utilzar uma variável para ilustrar melhor:
Conta := (Soma div 11) * 11; DVx := Soma - Conta; if DVx < 2 then Dv := 0 else Dv := 11 - DVx;
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.

Emerson Nascimento
06/03/2008
function ValidaCNH(sCNH: string; lExibeMsg: boolean): boolean; const String1 = ´090807060504030201´; String2 = ´100908070605040302´; var i,j,Digito: byte; Controle, DigitoInformado: string[2]; StringX: string; Soma: smallint; begin sCNH := Copy(´00000000000´+Trim(sCNH),(Length(Trim(sCNH))+11)-10,11 ); Controle := ´ ´; DigitoInformado := Copy( sCNH,10,2 ); StringX := String1; if sCNH <> ´00000000000´ then for i := 1 to 2 do begin Soma := 0; if i = 2 then StringX := String2; for j := 1 to 9 do Soma := Soma + ( StrToInt(sCNH[j]) * StrToIntDef( Copy( StringX,j+(j-1),2 ),0 ) ); Digito := Soma Mod 11; if Digito >= 10 then Digito := 0; Controle[i] := IntToStr( Digito )[1]; end; Result := Controle = DigitoInformado; if not Result and lExibeMsg then Application.MessageBox(´Número de CNH inválido!´,´Atenção´,mb_TaskModal + mb_IconWarning); end;

Cps.art
06/03/2008
Prestando mais atenção no código, percebi meu erro.
Mas a função completa que está no link:
http://delphiforall.blogspot.com/2008/09/algortimo-para-validao-de-cnh.html
não funciona.
Vamos falar da CNH nova, com 11 dígitos no seu número de registro.
Naquela função, a linha que contem [b:9122dbfc90]Digito := StrToInt(CnhN[10]);[/b:9122dbfc90], está errada, deveria ser [b:9122dbfc90]Digito := StrToInt(CnhN[11]);[/b:9122dbfc90], mas mesmo fazenda essa alteração, tambem não funciona.
Tome como exemplo esse número de CNH: [b:9122dbfc90]02650306461[/b:9122dbfc90].
É o número de minha CNH, válido portanto.
Tente validar esse número com a função do link, alterando a linha que citei acima, depois poste o resultado.
Quanto a essa outra função que você postou, ainda não testei, mas parece ser mais coerente.
Obrigado pela dica, e vão me desculpando por alguma gafe minha, pois sou um iniciante e só pretendo aprender com vocês, e colaborar se me for possível.
Abraços.

Cps.art
06/03/2008
Teste com o número da CNH que passei no post anterior.
Só valida como verdadeira se alterarmos o último digito (1), por 0(zero).
Vou postar aqui uns 20 números de CNH válidos para testarmos.
Vamos ver se conseguiremos achar esse bendito algoritimo do Detran.
Abraços.

Emerson Nascimento
06/03/2008
if Digito >= 10 then Digito := 0;
para:
if Digito >= 10 then Digito := 1;
mas para ter certeza seria necessário mais alguns numeros de CNH.

Emerson Nascimento
06/03/2008
if Digito > 9 then Digito := 11 - Digito;
a fórmula correta vai depender dos números a serem calculados.

Cps.art
06/03/2008
Trabalho no Detran aqui na minha cidade exclusivamente com CNH, então, quando da chegada de CNHs novas, 1ª habilitação, e como são feitas em lotes por cada Ciretran, elas vem numa sequência numérica que eu procurei observar, então dá pra perceber que a sequência está nos 9 primeiros dígitos da esquerda para a direita, como é obvio, então os 2 últimos dígitos são os DVs.
Exemplo da sequência que observei:
043973228XY
043973229XY
043973230XY
Tambem ouvi algum cometário que o primeiro dígito, o X da sequência acima, é calculado de forma completamente diferente do Y, algoritimo diferente.
Agora complicou mais ainda.
Pra quem quiser continuar tentando, aí vai uma série de 23 números de CNH para serem testados.
[b:c2e73664fb]04397322870, 04375701302, 02996843266, 04375700501, 02605113410, 03247061306, 01258750259, 00739751580, 03375637504, 02542551342, 01708111400, 00836510948, 04365445978, 04324384302, 04339482949, 01036520050, 01612581027, 00603454740, 04129251992, 03401740201, 03417248301, 00670431345, 03292694405.[/b:c2e73664fb]
Se encontrarem uma rotina que validem todos eles, certamente essa será a rotina correta.
Fico no aguardo de novas descobertas.
Abraços

Cps.art
06/03/2008
Testei diversos algoritimos numa planilha excel e acho que descobri o segredo do allgoritimo para o segundo DV.
Para o cálculo do 1º DV, o código do [b:67e98cf075]emerson.en[/b:67e98cf075] tá correto, para o segundo é meio diferente.
Pelo menos os 23 números de CNH que coloquei no post anterior validou 100¬.
Amanhã vou testar mais alguns números para ter certeza, depois vou montar a função e passo pra vocês.
Abraços.

Cps.art
06/03/2008
/////////////////////////
[b:04b1d5a323]function VRegCNH(nCNH: string): boolean;
var
j, Soma, Digito1, Digito2, Incr_dig2: integer;
sCNH, Dig_Forn, Dig_Enc : string;
begin
Result := False;
if length(Trim(nCNH)) < 11 then
Exit;
sCNH := Copy(nCNH,1,9);
Dig_Forn := Copy(nCNH,10,2);
Incr_Dig2 := 0;
[color=blue:04b1d5a323]// calcula o digito 1 (10º caractere)[/color:04b1d5a323]
Soma := 0;
for j := 9 downto 1 do
Soma := Soma + ( StrToInt(sCNH[j]) * (10-j));
Digito1 := Soma Mod 11;
if Digito1 >= 10 then
begin
Incr_Dig2 := -2; // [color=red:04b1d5a323]Aqui está o segredo[/color:04b1d5a323]
Digito1 := 0;
end;
[color=blue:04b1d5a323]// calcula o digito 2 (11º caractere)[/color:04b1d5a323]
Soma := 0;
for j := 9 downto 1 do
Soma := Soma + ( StrToInt(sCNH[j]) * (j)); // [color=red:04b1d5a323]Observem que aqui os multiplicadores estão invertidos[/color:04b1d5a323]
Digito2 := Soma Mod 11;
if Digito2 >= 10 then
begin
Digito2 := 0;
end;
Digito2 := Digito2 + Incr_Dig2;
Dig_Enc := IntToStr(Digito1)+IntToStr(Digito2);
Result := Dig_Forn = Dig_enc;
end;
end.[/b:04b1d5a323]
/////////////////////////////////
Testem, depois façam seus comentários.
Abraços.

Provisorio
06/03/2008
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!

Emerson Nascimento
06/03/2008

Provisorio
06/03/2008
A maioria que não validou teve 9 dígitos.
Faça o teste...
Abraços!

Cps.art
06/03/2008
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.

Cps.art
06/03/2008
É um algoritimo comum, igual ao que valida conta de banco e a maioria dos numeros com DV.
Existem 2 maneiras de se tratar o dígito verificador neste módulo.
1º) Algumas empresas não utiliza ´X´ como dígito, então se o resultado da operação for igual a ´10´, o dígito será ´0´. É o caso das CNHs antigas.
2º) Outras empresas, bancos principalmente, utiliza o ´X´ como dígito, então se o resultado da operação for ´10´ o dígito será ´X´.
Eu não utilizo esta função de validar CNHs antigas por que no meu trabalho não tenho essa necessidade, só utilizo validação de CNHs novas.
Se você tiver a necessidade de utilizar as 2 funções, pode juntar as 2 numa só, definindo no início da função se é CNH nova ou se é CNH antiga pela quantidade de caracteres, ai direciona para o cálculo pretendido.
No meu modo de entender, todos os caracteres do numero devem ser digitados, ou seja os zeros no início, para que a função possa distinguir cada tipo de CNH.
Se existirem 11 caracteres é CNH nova, se existirem 9 caracteres é CNH antiga.
Ai abaixo vai a função para as CNHs antigas.
[b:b180e1b57e]FUNCTION VMod110(PVMod110 : string) : string; stdcall;
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;[/b:b180e1b57e]
Teste e depois nos diga se funcionou.
Abraços.

Provisorio
06/03/2008
Testei as novas funções com os 3123 números. Testei a que valida as novas e as antigas, porém algumas (71 cnhs) que validam pelo site do Detran ainda não validam com estas funções.
Alguns exemplos são:
112274500
115478700
138273900
138876109
186499700
218659309
293766109
293821800
301823609
315558600
330157409
374723809
416345009
697159700
709245709
715334009
804310709
894476709
e
01137369409
01217567509
01417566409
01422691909
Estamos quase conseguindo, pois 71 em um universo de 3123 é um número bastante pequeno, porém...
De qualquer forma, agradeço imensamente pelas funções e explicação adicional!
Um abração!

Provisorio
06/03/2008
Eu não consegui passar deste percentual ainda...

Cps.art
06/03/2008
Fiqui uns dias sem micro, meu monitor pifou, estou usando um emprestado até chegar um novo.
Logo dou notícias.
Abraços

Cps.art
06/03/2008
Mudei algumas coisas na função, veja aí se valida todas agora.
Só as CNHs novas, com número de registro de 11 dígitos.
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;
Abraços a todos.

Cps.art
06/03/2008
É que os números foram tomados como ´inteiros´ e os zeros foram suprimidos, por isso a importancia de se tratar os números de CNH considerando os zeros.
Essas abaixo são números de CNHs novas, basta acrescentar os 2 zeros a esquerda:
112274500
115478700
138273900
138876109
186499700
218659309
293766109
293821800
301823609
315558600
330157409
374723809
416345009
697159700
709245709
715334009
804310709
894476709
Para validar os números de CNHs antigas, os PGUs, que são 9 dígitos, sendo os 8 primeiros a numeração sequencial e o último a direita (nono), o DV, vou postar logo abaixo a função.
Abraços

Cps.art
06/03/2008
[b:12b1b92828]FUNCTION VPguCnh(PVPguCnh : string) : string; stdcall;
var
j, Mult, Soma, Digito : integer;
PGU_Forn, Dig_Forn, Dig_Enc : string;
begin
Result := ´F´;
if length(Trim(PVPguCnh)) <> 9 then
Exit;
PGU_Forn := Copy(PVPguCnh,1,8);
Dig_Forn := Copy(PVPguCnh,9,1);
Soma := 0;
Mult := 2;
for j := 1 to 8 do
begin
Soma := Soma + (StrToInt(PGU_Forn[j]) * Mult);
Mult := Mult + 1;
end;
Digito := Soma Mod 11;
if Digito > 9 then
begin
Digito := 0;
end;
Dig_Enc := IntToStr(Digito);
if Dig_Forn = Dig_enc then
begin
Result := ´V´;
end;
if Dig_Forn <> Dig_enc then
begin
Result := ´F´;
end;
end;[/b:12b1b92828]
Aguardo retorno de vocês.
Abraços

Provisorio
06/03/2008
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!

Rafael Fig
06/03/2008
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!.

Ailtonfinan
06/03/2008
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.

Ailtonfinan
06/03/2008
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.

Ailtonfinan
06/03/2008
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]

Ailtonfinan
06/03/2008
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:
Conta := (Soma div 11) * 11; if (Soma - Conta) < 2 then Dv := 0 else Dv := 11 - (Soma - Conta);
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:
Conta := (Soma div 11) * 11; DVx := Soma - Conta; if DVx < 2 then Dv := 0 else Dv := 11 - DVx;
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.

Ailtonfinan
06/03/2008
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.

Roger Bifarat
06/03/2008

Roger Bifarat
06/03/2008

Luciano Chima
06/03/2008

Marcelo Freitas
06/03/2008
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.

Clovis Perazza
06/03/2008
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;

Jfpimentel
06/03/2008
Obrigado

Clovis Perazza
06/03/2008
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.

George Lopes
06/03/2008
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; } } }

George Lopes
06/03/2008
if (strlen(trim($pvRegCnh)) < 11) { // Caso tenha menos de 11 dígitos return false; }
por
if (strlen(trim($pvRegCnh)) < 11) { // Caso tenha menos de 11 dígitos return $this->validaCnhAntiga($pvRegCnh); }
e acrescentar o método abaixo, dentro da mesma classe:
private function validaCnhAntiga($pvPguCnh) { if (strlen(trim($pvPguCnh)) <> 9) { return false; } $pgu_forn = substr($pvPguCnh, 0, 8); $dig_forn = substr($pvPguCnh, 8, 1); $soma = 0; $mult = 2; for ($j = 0; $j < 9; $j++) { $soma = $soma + (intval(substr($pgu_forn, $j, 1)) * $mult); } $digito = $soma % 11; if ($digito > 9) { $digito = 0; } $dig_enc = strval($digito); if ($dig_forn == $dig_enc) { return true; } else { return false; } }

Clovis Perazza
06/03/2008

George Lopes
06/03/2008
Fiz uns um testes mas infelizmente não funcionou para todas as CNHs de 11 dígitos.

George Lopes
06/03/2008
Gente, na linha 67 da validação de 11 dígitos onde estava:
$dig_enc = strval($digito1) + strval($digito2);
deve ser trocado por
$dig_enc = strval($digito1) . strval($digito2);

Erena
06/03/2008
Desculpe a intromissão porque não sou programadora.
Já pesquisei em todos os lugares possíveis como calcular o DV da minha CNH vencida, sem foto e com 9 dígitos. Não consigo agendar a renovação. E pedi ajuda a universitários (desculpe a piada mas é verdade) com as fórmulas que vocês postaram e eles não conseguiram chegar a nenhum resultado. Eu, sinceramente, não entendo nada.
Se eu colocar meu número aqui será que alguém pode ajudar? Vai ser um favorzão. Se não for possível.....tudo bem, vou cortar os pulsos. Grata
Número: 024847147
Registro: 313609888
RJ

Clovis Perazza
06/03/2008
Estou perguntando por que aqui no estado de São Paulo eu sei qual é o site e sei como funciona pra fazer o agendamento de renovação.
Tem um lugar no site que pergunta se a CNH é "REGISTRO" ou "PGU".
Esse número (313609888) que você chama de Registro, na verdade é PGU, e o dígito está correto (31360988-8).
Esse outro número (024847147) é o número do Espelho (formulário) e não é solicitado em nenhum caso.
Me passe o link do site onde você tentou fazer o agendamento.
Me retorne depois pra saber se você conseguiu.
Abraços.

Clovis Perazza
06/03/2008
[img:descricao=Detran RJ - Agendamento Renovação CNH]http://arquivo.devmedia.com.br/forum/imagem/0-20150702-004739.jpg[/img]

Erena
06/03/2008
Valeu pelo retorno tão rápido. O PGU foi aceito e agora diz que o nome de minha mãe está errado. Como tenho que fazer várias modificações, como: nome de casada, endereço/município e o formulário é outro, vou tentar fazer mais tarde, com muita calma. Depois darei o retorno.
O Detran é RJ.
Obrigada, de verdade.
Erena

Willian
06/03/2008
public static function validaCNH($cnh){ // Subfunção para calcular os dígitos function CalculaDigito($identificacao, $digito){ // Inicializa a variável $soma = 0; // Atribui o fator de acordo com o dígito a ser calculado $digito == 1 ? $fator = 9 : $fator = 1; // Percorre os 9 primeiros dígitos da CNH for($i = 0; $i < 9; $i++){ // Multiplica o dígito pelo fator $soma += (int)$identificacao[$i] * $fator; // Incrementa ou decrementa o fator de acordo com o dígito a ser calculado $digito == 1 ? $fator-- : $fator++; } // Retorna o cálculo do dígito return $soma % 11; } // Verifica se a CNH informada é no modelo novo (11 dígitos) if(strlen($cnh) == 11){ // Recupera os 9 primeiros dígitos da CNH informada $identificacao = substr($cnh, 0, 9); //Chama a função que faz o cálculo do primeiro dígito $digito1 = CalculaDigito($identificacao, 1); //Chama a função que faz o cálculo do segundo dígito $digito2 = CalculaDigito($identificacao, 2); // Se o primeiro dígito é igual a 10, decrementa 2 do segundo if($digito1 == 10) $digito2 -= 2; // Se for menor que 0, incrementa 11 ao segundo dígito if($digito2 < 0) $digito2 += 11; // Zera os dígitos caso estes sejam maior que 9 if($digito1 > 9) $digito1 = 0; if($digito2 > 9) $digito2 = 0; // Armazena os dígitos do cálculo para efetuar a comparação (string)$digitosCalculo = $digito1 . $digito2; // Recupera os 2 últimos dígitos verificadores da CNH informada $digitos = substr($cnh, 9, 2); // Verifica se os dígitos verificadores são iguais ao do cálculo if($digitos == $digitosCalculo){ // Indica que a CNH é válida return true; } } // Verifica se a CNH informada é no modelo antigo (9 dígitos) if(strlen($cnh) == 9){ // Recupera os 8 primeiros dígitos da CNH informada $identificacao = substr($cnh, 0, 8); // Inicializa a variável $soma = 0; // Inicializa o fator $fator = 2; // Faz o cálculo do dígito for($i = 0; $i < 8; $i++){ // Multiplica o dígito pelo fator $soma += (int)$identificacao[$i] * $fator; // Incrementa o fator $fator++; } // Recupera o dígito $digitoCalc = $soma % 11; // Zera o dígito se for maior que 9 if($digitoCalc > 9) $digito = 0; // Recupera o dígito da CNH informada $digitoCnh = substr($cnh, 8, 1); // Verifica se o dígito verificador é iguail ao do cálculo if($digitoCnh == $digitoCalc){ // Indica que a CNH é válida return true; } } //CNH inválida return false; }

Clovis Perazza
06/03/2008
Você não imagina o tanto de incompetentes que trabalham nessas repartições.
Um abraço.

Willian
06/03/2008
Realmente existe algumas CNH's que não são validadas, mas sempre há a incerteza se o problema está na função ou na CNH, porém, tive em mãos algumas CNHs que foram validadas pelo site do DENATRAN mas não na função.
Já perdi as esperanças de achar um algoritmo que valide 100%, mas caso encontre algo que complemente a função estarei postando aqui.
Abraços.

Clovis Perazza
06/03/2008
Vamos observar que as CNH NOVAS (Registro) tem 11 dígitos no número e as ANTIGAS (PGU) só 9 dígitos.
Vamos tomar como base a CNH NOVA REGISTRO "00756004182" ( a última da folha 2 da relação de CNHs suspensas do link que você citou).
Ela é NOVA (Registro) pois chequei aqui e validou, porém, se na digitação desse número se suprimir os 2 ZEROS da esquerda, ela passa a ter somente 9 dígitos, o que sugere que ela seja Antiga (PGU) e aí a validação será falsa.
Para que seu código funcione corretamente, é necessário que o USUÁRIO saiba que os zeros devem ser digitados.
O código que postei para validação de CNHs NOVAS (Registro) validam todas elas, e se você conseguir passar para PHP exatamente como o meu, certamente vai validar todas.
Digo isso por que notei que seu código parecer não calcular o SEGUNDO DÍGITO com as particularidades necessárias.
Tente fazer em PHP exatamente como meu código que vai funcionar.
Veja os posts do George Tavares Lopes aqui neste tópico.
Qualquer coisa entre em contato.
Se quiser o meu código completo, me mande seu email que eu te mando.
Abraços a todos.

Rodrigo
06/03/2008

Everson Carvalho
06/03/2008
Não montei a função ainda, só estou fazendo testes no Excel para descobrir a forma de calcular esses DVs.
A CNH tem 2 números, 1 em preto, na vertical do lado esquerdo da foto e no verso do lado esquerdo da assinatura do delegado, e é chamdo de ´ESPELHO´, o outro fica abaixo da foto, em vermelho e é chamado de ´REGISTRO´.
O primeiro tem 8 dígitos e um DV, e a informação da letra a) da Res. do Denatran ([b:25f0df1472]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:25f0df1472]), tambem está furada para o DV do espelho, pois tem espelho com DV 1, o que não poderia acontecer.
Já o segundo número, o REGISTRO, que tem 2 DVs, na maioria dos casos consegui uma forma de validar, porem, para os números que tem DVs ´00´, a mesma regra não se aplica, e para DVs ´01, 02, 03....09´, em alguns casos tambem não.
Trabalho no Detran aqui na minha cidade e cuido do setor de CNH.
Estou tentando montar um sisteminha de protocolo digital para a agencia do Detran aqui da minha cidade, e um para as Auto-Escolas pra agendamento de Provas (Teórica e Prática) para evitar excesso de digitação desnecessária, ou seja, elas me passariam o agendamento em disquetes, e eu compilaria tudo num BD para controle de aprovações e de novos agendamentos, e para isso eu preciso que os números de REGISTRO, assim como CPF e RENACH, fossem validados na digitação para evitar erros.
O CPF e o RENACH não tem problema, mas esse do REGISTRO não há meio de descobrir.
O Denatran não fornece o algorítimo, e não sei porque fazem tanto segredo, se a própria RECEITA FEDERAL forneceu o do DV do CPF e CGC.
Fica então a nosso cargo descobrir isso, mesmo que seja pra auxiliar no próprio serviço do Detran.
Não dá pra entender o que se passa na cabeça desse povo.
Mas vamos tentando que descobriremos.
Abraços.
Me chamou atenção a parte "CPF e RENACH não tem problema". Você teria então a fórmula de cálculo de validação do RENACH?

Rogério Lima
06/03/2008
Não sei se este tópico ainda é valido, mas eu fiz uso da ultima versão aqui disponibilizada e em um range de 9mil documentos, alguns deram como invalidos mas teve uma que diz ser invalido, no entanto, ela seria válido. Seria o doc: 22522791500, eu estava utilizando o "Validador Online de CNH" da 4devs.com.br, para certificar que meus registros avaliados estariam corretos ou não e esse doc o site diz que é valido. A checagem do Dv2 retornou 8 que invalidaria a ação em atribuir o "zero" por não ser maior que 9.
Pergunto: alguém saberia dizer que tivemos alguma atualização nesta rotina , quanto aos DV serem iguais a ZEROS...