Algoritmo para obtener la letra del NIF
El número de identificación fiscal (NIF) español es un código único que identifica a todos los ciudadanos españoles a efectos fiscales. Partiendo del tradicional documento nacional de identidad, DNI, añade a éste una letra que actúa como elemento verificador.
Contenido |
Algoritmo
La letra del NIF se obtiene a partir de un algoritmo conocido como módulo 23. El algoritmo consiste en aplicar la operación aritmética de módulo 23 al número del DNI. El módulo 23 es el número entero obtenido como resto de la división entera del número del DNI entre 23. El resultado es un número comprendido entre el 0 y el 22. En base a una tabla conocida se asigna una letra. La combinación del DNI con esa letra es el NIF.
Este mismo algoritmo también puede utilizarse para el cálculo del NIE. En el caso que el NIE empiece por X, se calcula despreciando la X y utilizando los 7 dígitos, si el NIE empieza por Y, se sustituye la letra Y por el número 1, si el NIE empieza por Z, se sustituye la letra Z por el número 2 y se realiza el mismo cálculo.
El algoritmo no se aplica para obtener el Código de Identificación Fiscal (CIF), que es el "NIF" propio de las personas jurídicas, pues la letra que tiene no se basa en una fórmula, sino que identifica el tipo de entidad (p.e. B para Sociedades Limitadas; G para Asociaciones sin ánimo de lucro y otros tipos no definidos, etc.).
Tabla de asignación
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| T | R | W | A | G | M | Y | F | P | D | X | B | N | J | Z | S | Q | V | H | L | C | K | E |
No se utilizan las letras: I, Ñ, O, U
La I y la O se descartan para evitar confusiones con otros caracteres, como 1, l o 0.
Se usan veintitrés letras por ser este un número primo.
Ejemplos
Algunos ejemplos de la implementación de este algoritmo para distintos lenguajes de programación son:
Ada
Este es el código fuente en Ada para calcular la letra del NIF.
function Letra_Nif (Dni : Positive) return Character is Letras : constant String := "TRWAGMYFPDXBNJZSQVHLCKE"; begin return Letras ((Dni mod Letras'Length) + 1); end Letra_Nif;
AppleScript
Código fuente del cálculo de la Letra del NIF en AppleScript
on LetraDNI(dni) return character (1 + (dni as integer) mod 23) of "TRWAGMYFPDXBNJZSQVHLCKE" end LetraDNI
ASP 3.0 VBScript
Function sacaLetra(ByVal dni) Dim tabla,pos tabla = Array("T","R","W","A","G","M","Y","F","P","D","X","B","N","J","Z","S","Q","V","H","L","C","K","E") pos = dni mod 23 sacaLetra = tabla(pos) End Function
Y para Validar el NIF:
Function validaNIF(ByVal nif) Dim dni If Len(nif)<7 Then validaNIF = false Else dni = Left(nif,Len(nif)-1) validaNIF = UCase(nif)=dni&sacaLetra(dni) End If End Function
Bourne shell script
echo TRWAGMYFPDXBNJZSQVHLCKE | cut -c $(( $(( $1 % 23 )) + 1 ))
otra forma sin utilizar las órdenes externas (echo y cut)
LETRANIF="TRWAGMYFPDXBNJZSQVHLCKE" DNI=12345678 echo ${LETRANIF:$DNI % 23:1}
C
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* numero de cifras para el DNI */
#define kTAM 8
int main(int argc, char *argv[])
{
int dni;
char letra[] = "TRWAGMYFPDXBNJZSQVHLCKE";
if (argc != 2) {
printf("Uso: %s <DNI>\n", argv[0]);
} else {
if (strlen(argv[1]) != kTAM) {
puts("DNI no valido.");
} else {
dni = atoi (argv[1]);
dni %= 23;
printf("%s-%c\n", argv[1],letra[dni]);
}
}
return 0;
}
C++
#include <iostream> using namespace std; int main() { int dni; cout << "Introduce el DNI: "; cin >> dni; cout << "TRWAGMYFPDXBNJZSQVHLCKE"[dni % 23] << endl; fflush(stdin); printf("j"); getchar(); }
C++ Builder
AnsiString Letra(AnsiString Nif) { int nSuma, nSumaPar, nSumaNon; if (Nif.IsEmpty()) return (""); if (isdigit(Nif.c_str()[0]) || AnsiString("KLMXYZ").Pos(Nif.SubString(1, 1)) != 0) // Persona física { if (AnsiString("XYZ").Pos(Nif.SubString(1, 1)) != 0) Nif = iif(Nif.SubString(1, 1) == "Z", "2", iif(Nif.SubString(1, 1) == "Y", "1", "0")) + Nif.SubString(2, Nif.Length()); else if (AnsiString("KLM").Pos(Nif.SubString(1, 1)) != 0) Nif = Nif.SubString(2, Nif.Length()); return ("TRWAGMYFPDXBNJZSQVHLCKE"[StrToInt(Trim(Nif)) % 23]); } else // Persona jurídica { if (AnsiString("ABCDEFGHJNPQRSUVW").Pos(Nif.SubString(1, 1)) == 0) return (""); nSumaPar = 0; nSumaNon = 0; for (int nLetra = 2; nLetra < 9; nLetra += 2) { if (nLetra < 8) nSumaPar += StrToInt(Nif.SubString(nLetra + 1, 1)); nSumaNon += ((2 * StrToInt(Nif.SubString(nLetra, 1))) % 10) + ((2 * StrToInt(Nif.SubString(nLetra, 1))) / 10); } nSuma = nSumaPar + nSumaNon; nSuma = 10 - (nSuma % 10); if (nSuma == 10) nSuma = 0; if (AnsiString("ABDEFGHJUV").Pos(Nif.SubString(1, 1)) == 0) return ("ABCDEFGHIJ"[nSuma]); else return (FormatFloat("0", nSuma)); } }
VC++ 2008
/// <summary> Genera la letra correspondiente a un DNI. </summary> public: System::String^ LetraNIF(System::String^ dni) { System::String^ Correspondencia = "TRWAGMYFPDXBNJZSQVHLCKE"; return Correspondencia[ Convert::ToInt32(dni) % 23 ].ToString() ; }
C#
/// <summary> Tabla de asignación. </summary> public const string Correspondencia = "TRWAGMYFPDXBNJZSQVHLCKE"; /// <summary> Genera la letra correspondiente a un DNI. </summary> /// <param name="dni"> DNI a procesar. </param> /// <returns> Letra correspondiente al DNI. </returns> public char LetraNIF(string dni) { int n; //if ((dni == null) || (dni.Length != 8) || (!int.TryParse(dni, out n))) if ((dni == null) || (dni.Length != 9) || (!int.TryParse(dni.Substring(0,8), out n))) { throw new ArgumentException("El DNI debe contener 8 dígitos."); } return Correspondencia[n % 23]; } /// <summary> Genera la letra correspondiente a un NIE. </summary> /// <param name="nie"> NIE a procesar. </param> /// <returns> Letra correspondiente al NIE. </returns> public char LetraNIE(string nie) { int n; //Linea original, editado en caso practico //if ((nie == null) || (nie.Length != 8) || ((char.ToUpper(nie[0]) != 'X') && (char.ToUpper(nie[0]) != 'Y') && (char.ToUpper(nie[0]) != 'Z')) || (!int.TryParse(nie.Substring(1), out n))) if ((nie == null) || (nie.Length != 9) || ((char.ToUpper(nie[0]) != 'X') && (char.ToUpper(nie[0]) != 'Y') && (char.ToUpper(nie[0]) != 'Z')) || (!int.TryParse(nie.Substring(1,7), out n))) { throw new ArgumentException("El NIE debe comenzar con la letra X, Y o Z seguida de 7 dígitos."); } switch (char.ToUpper(nie[0])) { case 'X': return Correspondencia[n % 23]; case 'Y': return Correspondencia[(10000000 + n) % 23]; case 'Z': return Correspondencia[(20000000 + n) % 23]; default: return '\0'; } }
Fortran
program TREVISONE implicit none integer :: numero character(len=23) :: string='TRWAGMYFPDXBNJZSQVHLCKE' integer :: nif write(*,'(a)') 'Este programa calcula su letra del NIF a partir de su numero de DNI' write(*,'(a)') 'Introduzca su TREVISONE' read(*,*) numero nif=mod(numero,23)+1 write(*,'(a,2x,a)') 'Su letra del NIF es:', string(nif:nif) end program TREVISONE
Java
public static final String NIF_STRING_ASOCIATION = "TRWAGMYFPDXBNJZSQVHLCKE"; /** * Devuelve un NIF completo a partir de un DNI. Es decir, añade la letra del NIF * @param dni dni al que se quiere añadir la letra del NIF * @return NIF completo. */ public static String letraDNI(int dni) { return String.valueOf(dni) + NIF_STRING_ASOCIATION.charAt(dni % 23); }
JavaScript
// devuelve la letra correspondiente a un número DNI function letraDni(dni) { var lockup = 'TRWAGMYFPDXBNJZSQVHLCKE'; return lockup.charAt(dni % 23); }
Ejecutable en navegador:
Javascript:letraDni();
Pascal/Delphi
Function IsValidNIF(ANIF: String): Boolean; Var sChar, sDNI: String; begin Result := FALSE; ANIF := UpperCase(ANIF); If Length(Trim(ANIF)) = 9 Then Begin If ANIF[1] In ['0'..'9'] THen sDNI := Copy(ANIF, 1, 8) Else sDNI := Copy(ANIF, 2, 7); sChar := Copy('TRWAGMYFPDXBNJZSQVHLCKE', StrToInt(sDNI) Mod 23 + 1, 1); Result := sChar = ANIF[9]; End; end;
Perl
sub LetraDNI {
my $dni = shift;
return substr( 'TRWAGMYFPDXBNJZSQVHLCKE', $dni % 23, 1);
}
PHP
$numero = "12345678"; //asignación del número de DNI
function letra_nif($dni) {
return substr("TRWAGMYFPDXBNJZSQVHLCKE",strtr($dni,"XYZ","012")%23,1);
}
echo 'El NIF del DNI "'.$numero.'" es "'.$numero.letra_nif($numero).'"';
Python
DNI=12345678
NIF='TRWAGMYFPDXBNJZSQVHLCKE'
print "El NIF del DNI es", NIF[DNI%23]
Ruby
puts "TRWAGMYFPDXBNJZSQVHLCKE"[gets.to_i % 23].chr
Visual Basic
Private Function NIF(DNI As Long)
NIF = DNI & "-" & Mid$("TRWAGMYFPDXBNJZSQVHLCKE", (DNI Mod 23) + 1, 1)
End Function
Excel
=CONCATENAR(A1;MED("TRWAGMYFPDXBNJZSQVHLCKE";RESTO(A1;23)+1;1)) =CONCATENAR(A1;EXTRAE("TRWAGMYFPDXBNJZSQVHLCKE";RESIDUO(A1;23)+1;1)) =CONCATENATE(A1,MID("TRWAGMYFPDXBNJZSQVHLCKE",MOD(A1,23)+1,1)) En calc (OpenOffice) =CONCATENAR(A1,MID("TRWAGMYFPDXBNJZSQVHLCKE",RESIDUO(A1,23)+1,1))
Siendo A1 la celda de origen del DNI sin letra.
PL-SQL
DECLARE @nif VARCHAR(9) DECLARE @dni int SET @dni = 12345678 SET @nif = CONVERT(VARCHAR(8),@dni) + SUBSTRING('TRWAGMYFPDXBNJZSQVHLCKE', @dni % 23 + 1, 1) print @nif
en sentencias SELECT:
SELECT CONVERT(VARCHAR(8),tablaPersonas.dni) + SUBSTRING('TRWAGMYFPDXBNJZSQVHLCKE', tablaPersonas.dni % 23 + 1, 1) FROM tablaPersonas
o más simple para ORACLE:
SELECT dni||SUBSTR('TRWAGMYFPDXBNJZSQVHLCKET',MOD(dni,23)+1,1) FROM tablaPersonas
siendo tablaPersonas la tabla con el dato de usuario y el campo dni el origen del DNI y en formato entero (int).
SAP
FORM resultado USING VALUE(GV_NUMBER) DATA GV_result(9) TYPE c. DATA lt_letters(24) TYPE c VALUE 'TRWAGMYFPDXBNJZSQVHLCKE'. DATA lv_num TYPE i. DATA lv_number(8) type n. lv_number = gv_number. lv_num = gv_number MOD 23. gv_character = lt_letters+lv_num(1). CONCATENATE lv_number gv_character INTO gv_result. ENDFORM. " resultado
Siendo gv_result el nº de nif con la letra.
PL/1
CALCULAR_LETRA: PROC(DNI) RETURNS(CHAR);
DCL DNI PIC '99999999';
DCL LETRA CHAR INIT (' ');
DCL LETRAS CHAR(23) INIT ('TRWAGMYFPDXBNJZSQVHLCKE');
DCL VECTOR(23) DEFINED LETRAS CHAR(1);
DCL RESTO DEC FIXED(2) INIT(0);
RESTO = MOD(DNI,23)+1;
LETRA = VECTOR(RESTO);
RETURN(LETRA);
END CALCULAR_LETRA;
Previamente hay que declarar en el programa que se importa la función del sistema para hallar restos:
DCL (MOD) BUILTIN;
Nota en caso DNI y NIE Prácticos función c#
Corrección comprobada con datos reales: El DNI esta compuesto de 9 caracteres 8digitos+Letra. El NIE esta compuesto de 9 caracteres Letra+7digitos+Letra, debe tenerse esto encuenta al realizar las validaciones de tamaño. En la función C#(la única que he testeado) en las comparaciones longitud y conversión a entero, debe poner (nie.Length != 9) y (!int.TryParse(nie.Substring(1,7), out n) o jamas aceptara un NIE real como valido.
Enlaces externos
- CalculaDNI.com - Calcula la letra del NIF a partir del DNI
- Calcula la Letra del DNI o NIF
- Página 'DNIe' de Glosario de Tecnología.
- Herramienta desarrollada en C que genera DNIs, valida NIFs, verifica DNIs, etc.
- Programas en Javascript para calcular la letra del NIF.
- Letra del NIF en Excel
- Código de validación de NIFs, NIEs, DNIs y CIFs en PHP