Validação do número de registro de CNH

06/03/2008

0

Olá pessoal.

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

Cps.art

Responder

Post mais votado

27/03/2013

A função de validação de números de registro de CNHs novas (com foto) vai abaixo:



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

Clovis Perazza
Responder

Mais Posts

14/08/2009

Provisorio

Meu amigo cps.art, desculpa a demora ao responder... mas é que depois de diariamente verificar que não tinha resposta, então abandonei o forum por uns tempos!

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!


Responder

01/02/2012

Rafael Fig

Pessoal,

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!.
Responder

12/05/2012

Ailtonfinan

[b:8147beb8c0]Provisório[/b:8147beb8c0], o que o [b:8147beb8c0]emerson.en[/b:8147beb8c0] disse está correto.
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.
Responder

12/05/2012

Ailtonfinan

Achei esta rotina
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.
Responder

12/05/2012

Ailtonfinan

Mas não informa diretamente como fazer o algorítmo:

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]


Responder

12/05/2012

Ailtonfinan

[quote:f3064a86dd=´cps.art´]Eu já tinha visto essa rotina José Henrique.

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.
Responder

12/05/2012

Ailtonfinan

A função apresentada está quase correta!

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.
Responder

07/01/2013

Roger Bifarat

Boa tarde pessoal. preciso de ajuda. se possivel, nao entendo nada de dephi, porem necessito desvendar as dvs das cnhs nao preciso nem validar 100% alguem por favor me ajuda. podemos trocar favores.
Responder

07/01/2013

Roger Bifarat

to em desespero. nao consigo entender! preciso muito dissu
Responder

10/03/2013

Luciano Chima

Alguém sabe a formula matemática para calcular o digito verificador do 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.
Responder

27/03/2013

Marcelo Freitas

Acho que em JavaScript ficaria algo assim (para 11 digitos)

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.
Responder

27/03/2013

Clovis Perazza

LUCIANO F CHIMA, tente utilizar o algoritimo MODULO 11, usado para calcular dígito de contas de bancos, com a diferença que no número identificador da CNH não tem dígito "X".
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;
Responder

22/10/2014

Jfpimentel

Boa tarde tentei mas nao consegui, será que vc consegui o codigo de segurança da cnh n 02641808140
Obrigado
Responder

22/10/2014

Clovis Perazza

Olá Jfpimentel, sobre esse número de registro da CNH 02641808140, o que posso lhe dizer é que é um número válido.
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.
Responder

26/11/2014

George Lopes

Olá, pessoal,

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;
        }
    }

}
Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar