Validate a 'Seguridad Social' number (Only for Spain)  

Send By: Radikal (Q3 Team)
Web : http://www.q3.nu
Email: radikal@q3.nu
Date: 10/08/00

Tip accessed 2767 times

 


Truco desarrollado a partir de un texto remitido por Fernando P. Nájera_Cano


Se trata de una cifra de 11 dígitos para el caso de las cuentas de cotización de empresas, y de 12 dígitos en el caso del número de un trabajador.
Los dos últimos dígitos constituyen los dígitos de control.
Estas dos ultimas cifras del número completo, debe ser el resto de dividir todo el número exceptuando los dos ultimos digitos, que son los de control entre 97.

Ejemplo:
Tenemos el número:


      28/1234567/42



Así que hacemos:

 281234567 mod 97 = 42



Aqui tienes una función Delphi para validar estos números:


 procedure TForm1.Button1Click(Sender: TObject);

 function ValidaDCSS(Numero:string):boolean;
 var
   Limpio : string;
   i      : integer;
   uno, dos: integer;
 begin
   {El numero de la seguridad social debe entrarse con este
    formato:
            28/1234567/40
    o bien:
            28/12345678/40
    En función de que se trate del numero de una empresa
    o del numero de un trabajador.
    }
    Limpio:='';
    for i:=1 to Length(Numero) do
      if Numero[i] in ['0'..'9'] then Limpio:=Limpio+Numero[i];

    {Si no tiene 11 ó 12 digitos, no es válido}
    if (Length(Limpio)=11) or (Length(Limpio)=12) then
    begin
        Result:= StrToInt( copy(Limpio,1,Length(Limpio)-2) )
                 mod 97 =
                 StrToInt( copy(Limpio,Length(Limpio)-1,2) );
    end
      else Result:=FALSE;

 end;


 begin
   if ValidaDCSS('28/1234567/42')
     then ShowMessage('Válido')
     else ShowMessage('No Válido');
 end;




Actualizado el 29/11/99
Según me comenta Jose Vte Machi Ortega (starseg@ctv.es), la función falla con algunos números:

El codigo de la funcion seria incorrecto en el caso de que estubieramos trabajando con provincias como Valencia que es mi caso.

El código deberia ser:


 if (Length(Limpio)=11) or (Length(Limpio)=12) then    begin
    Result:= StrToInt64( copy(Limpio,1,Length(Limpio)-2) )
             mod 97 =
             StrToInt( copy(Limpio,Length(Limpio)-1,2) );    end
    else Result:=FALSE;



Por que si no da un error por que el nº obtenido no es un entero valido ( por ejemplo 4612345678 ) pruebalo y veras.

Esto es correcto, sólo que hay un problema: el tipo Int64 sólo está disponible a partir de la versión 4 de Delphi...
Para todos aquellos retrógrados (como yo...) que aún usamos Delphi3, una posible solución sería la de trabajar con números float.
Aqui teneis una variación de la función usando float:


 procedure TForm1.Button1Click(Sender: TObject);

   function ValidaDCSS(Numero:string):boolean;
   var
     Limpio : string;
     i,dos  : integer;
     uno    : real;
   begin
     {El numero de la seguridad social debe entrarse con este
      formato:
              28/1234567/40
      o bien:
              28/12345678/40
      En función de que se trate del numero de una empresa
      o del numero de un trabajador.
      }
      Limpio:='';
      for i:=1 to Length(Numero) do
        if Numero[i] in ['0'..'9'] then Limpio:=Limpio+Numero[i];

      {Si no tiene 11 ó 12 digitos, no es válido}
      if (Length(Limpio)=11) or (Length(Limpio)=12) then
      begin
          Uno:=StrToFloat( copy(Limpio,1,Length(Limpio)-2) );
          Dos:=StrToInt( copy(Limpio,Length(Limpio)-1,2) );
          Result:=Trunc( ( (Uno/97)-Trunc(Uno/97) )*97 )=Dos;
      end
        else Result:=FALSE;
   end;

 begin
   if ValidaDCSS('46/12345678/43')
     then ShowMessage('Válido')
     else ShowMessage('No Válido');
 end;




Sent by: Emilio López (emiliolr@teleline.es)

El motivo de mi e-mail es para decirte que en la solución propuesta para validar el número de la seguridad social utilizando las versiones anteriores a delphi4, he comprobado que existe un problema en la linea:


 Result:=Trunc( ( (Uno/97)-Trunc(Uno/97) )*97 )=Dos;



mi solución propuesta es la siguiente:


 Result:=Round( ( (Uno/97)-Trunc(Uno/97) )*97 )=Dos;



de lo contrario existen numeros como por ejemplo el mio que tendria que dar 79 y con tu linea da 78 este problema viene precisamente por utilizar Trunc cuando lo que se debe es de redondear.


Optimization sent by: Gustavo Mollá Vayá (gmolv@nexo.es)

Ante las fórmulas


 
 Result:=Trunc( ( (Uno/97)-Trunc(Uno/97) )*97 )=Dos;
 Result:=Round( ( (Uno/97)-Trunc(Uno/97) )*97 )=Dos;



He de decir que los problemas que habeis tenido se pueden solucionar muy fácilmente. Vosotros utilizais 6 operaciones  mas la de comparación.
La fórmula que yo propongo gasta 4 mas la de comparación y no entrañaría mas problemas


 
 Result:=( Uno - Trunc(Uno/97) *97)=Dos;


 
¿Por qué?:


 
 ( ( uno / 97 ) - Trunc (uno / 97 ) ) * 97      =
 (  uno / 97 ) * 97 - Trunc (uno / 97 ) * 97  =
 (  uno * 97 / 97 ) - Trunc (uno / 97 ) * 97  =
 uno  - Trunc (uno / 97 ) * 97  

 

Por otra parte tenemos que "uno" es realmente un entero (aunque esté definido como un real), es decir, no tiene decimales. Trunc( uno / 97 ) da como resultado un entero. Un entero por un entero por un entero da como resultado un entero, por tanto, no hace falta redondear o truncar o hacer ninguna operación posterior.
Pero alguno saltará y dirá que Dos es entero. Muy bién, convertimos Dos en real y ya podemos comparar. No obstante en Delphi 5 no me da ningún problema al comparar un integer con un double o un real.


Updated at 15/07/2000 (Round.Trunc)


Updated at 10/08/2000 (Optimization)