Gå til innhold

Algoritme for sjekk av fødselsnummer


Anbefalte innlegg

Jeg trenger en algoritme eller en kodesnutt som kan returnere true eller false på om et fødselsnummer er gyldig eller ikke.

 

Fant forøvrig noe info her:

http://www.matematikk.org/pub/mattetekst/Persnr/

 

Som viser hvordan algoritmen er, men skulle gjerne hatt en som er ferdig skrevet i C# eller Java så jeg slipper å knote med dette og sansynligvis få det feil :-)

 

Hvis ingen kommer opp med noe, får jeg vel heller bite i gresset og skrive det selv.

 

 

Takk for eventuelle tips !

Lenke til kommentar
Videoannonse
Annonse

La den til i kodebilioteket mitt. Med litt forandringer. Den har blandt annet støtte for D-nummer, Datosjekking og oppdatert invididnummer som takler folk født etter år 2000. Returnerer kjønn eller kaster exception ved feil i fodselsnummeret.

 

Sjekker ikke invididnummeret opp mot fødselsår.

 

namespace LIB.Validation
{
   public class FodselsNummer
   {
       public enum Gender : int
       {
           Female = 0,
           Male = 1
       }

       public static Gender Check(string fnr)
       {
           if (fnr.Length != 11)
               throw new InvalidLengthException();

           // Valid date?  D-Number = +4
           string Date = (fnr[0] <= '3') ? fnr.Substring(0, 6) : ((fnr[0] - '4') + fnr.Substring(1, 5));
           DateTime tmp;
           if (DateTime.TryParseExact(Date, "ddMMyy", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out tmp) == false)
               throw new InvalidDateException();

           int[] n = new int[11];
           int tmp2 = 0;
           for (int i = 0; i < 11; i++)
               if (int.TryParse(fnr[i].ToString(), out tmp2))
                   n[i] = tmp2;
               else
                   throw new InvalidCharactersException();

           // Control number 1
           int k1 = 11 - (3 * n[0] + 7 * n[1] + 6 * n[2] + 1 * n[3] + 8 * n[4] + 9 * n[5] + 4 * n[6] + 5 * n[7] + 2 * n[8]) % 11;
           if (k1 == 11) k1 = 0;

           if (k1 == 10 || k1 != n[9])
               throw new InvalidControlNumberException();

           // Control number 2
           int k2 = 11 - (5 * n[0] + 4 * n[1] + 3 * n[2] + 2 * n[3] + 7 * n[4] + 6 * n[5] + 5 * n[6] + 4 * n[7] + 3 * n[8] + 2 * k1) % 11;
           if (k2 == 11) k2 = 0;

           if (k2 == 10 || k2 != n[10])
               throw new InvalidControlNumberException();

           // Sex
           return (Gender)(n[8] & 1);
       }

       public class InvalidFodselsNumberException : ApplicationException
       {
       }

       public class InvalidCharactersException : InvalidFodselsNumberException
       {
       }

       public class InvalidControlNumberException : InvalidFodselsNumberException
       {
       }

       public class InvalidDateException : InvalidFodselsNumberException
       {
       }

       public class InvalidLengthException : InvalidFodselsNumberException
       {
       }
   }
}

Endret av jorn79
Lenke til kommentar
Sjekk denne du: http://kjappsms.no/ssn.aspx

 

Har lagt ut hele funksjonen "submit_Click" under. Skjemaet funker også, så du kan kontrollere med fødselsnummer hvis du vil :)

8241208[/snapback]

 

 

Manfred;

 

takk for rask løsning men den er desverre ikke slik den skal. Jeg har også laget en løsning, men den feiler på det samme som din - prøv f eks dette nummeret:

 

65038300827

 

Dette nummeret blir godkjent i mitt program, og også i ditt:

"Dette er en kvinne - Passerte alle tester"

 

Men det er jo opplagt at det ikke er et gyldig nummer, all den tid 65. mars ikke eksisterer....

 

Har du noen tips til hva som gjør at dette nummeret godkjennes?

Lenke til kommentar
65038300827

 

Dette nummeret blir godkjent i mitt program, og også i ditt:

"Dette er en kvinne - Passerte alle tester"

 

Men det er jo opplagt at det ikke er et gyldig nummer, all den tid 65. mars ikke eksisterer....

 

Har du noen tips til hva som gjør at dette nummeret godkjennes?

8245796[/snapback]

 

Dette er faktisk et gyldig personnummer. Dette er fordi det er et D-nummer (personnummer for utlendinger i Norge).

Fødselsdatoen for dette nummeret er: 25.03.1983. Og denne datoen eksisterer.

Lenke til kommentar
65038300827

 

Dette nummeret blir godkjent i mitt program, og også i ditt:

"Dette er en kvinne - Passerte alle tester"

 

Men det er jo opplagt at det ikke er et gyldig nummer, all den tid 65. mars ikke eksisterer....

 

Har du noen tips til hva som gjør at dette nummeret godkjennes?

8245796[/snapback]

 

Dette er faktisk et gyldig personnummer. Dette er fordi det er et D-nummer (personnummer for utlendinger i Norge).

Fødselsdatoen for dette nummeret er: 25.03.1983. Og denne datoen eksisterer.

8246043[/snapback]

 

Aha, se der ja, kan lønne seg å faktisk LESE det som står på wikipedia :-)

 

Takk for alle innlegg her!

Lenke til kommentar

Det står også som kommentar i koden min: "Husk at i et D-nummer legges det til 40 på dagen." ;)

 

Edit: Eneste sjekken jeg la på individnummeret var den for mennesker født mellom 1855 og 1899, da det er lite sannsynlig at jeg vil få en person registrert som er godt over 100 år :p

 

Edit2: Men dette er en litt dum test, fordi de begynner å tildele disse individnummerne nå snart igjen, siden vi begynner å gå litt tom for numre.

Endret av Manfred
Lenke til kommentar
65038300827

 

Dette nummeret blir godkjent i mitt program, og også i ditt:

"Dette er en kvinne - Passerte alle tester"

 

Men det er jo opplagt at det ikke er et gyldig nummer, all den tid 65. mars ikke eksisterer....

 

Har du noen tips til hva som gjør at dette nummeret godkjennes?

8245796[/snapback]

 

Dette er faktisk et gyldig personnummer. Dette er fordi det er et D-nummer (personnummer for utlendinger i Norge).

Fødselsdatoen for dette nummeret er: 25.03.1983. Og denne datoen eksisterer.

8246043[/snapback]

 

Aha, se der ja, kan lønne seg å faktisk LESE det som står på wikipedia :-)

 

Takk for alle innlegg her!

8247103[/snapback]

 

 

Ja så det etterpå :-)

Lenke til kommentar
  • 5 år senere...

Jeg har skapt en C# klasse, basert på kodene jeg fant i sammenheng med denne tråden.

Klassen sjekker både vanlig fødselsnummer, D-nummer og H-nummer.

Med hjelp av flere Action<> properties kan reageres på forskjellige grunn hvorfor nummeret ikke er gyldig.

 

 

// Based on: http://kjappsms.no/ssn.aspx
//	 and: https://www.diskusjon.no/index.php?showtopic=738727

using System;
namespace Tools
{
  /// <summary>
  /// Class which checks the norwegian birth number.
  /// <para></para>
  /// Also D-nummer og H-nummer is recognized if the parameters allow this.
  /// <para></para>
  /// If it is necessary to respond to the reasons why a number is recognized as false,
  /// you must use the static Action delegates.
  /// <para></para>
  /// The ctor only loads the birth number into a local field.
  /// Use the check method to start the check.
  /// <para></para>
  /// The result of the Check is a boolean.
  /// <para></para>
  /// Other informations can be getted by some properties with get accessor.
  /// </summary>
  public class NorwegianBirthNumberChecker
  {
  public static Action<string> OnWrongCharacters { get; set; }
  public static Action<string> OnWrongLength { get; set; }
  public static Action<string> OnWrongDate { get; set; }
  public static Action<string> OnYearLess1900 { get; set; }
  public static Action<string> OnWrongCheckNumber1 { get; set; }
  public static Action<string> OnWrongCheckNumber2 { get; set; }
  public static Action<string> OnHNumberRecognized { get; set; }
  public static Action<string> OnDNumberRecognized { get; set; }
  public static Action<string> OnFemaleRecognized { get; set; }
  public static Action<string> OnMaleRecognized { get; set; }

  private readonly string _fnr;
  private string _day;
  private string _month;
  private string _year;
  private string _individual;
  private string _k1;
  private string _k2;
  private int _d1;
  private int _d2;
  private int _m1;
  private int _m2;
  private int _y1;
  private int _y2;
  private int _i1;
  private int _i2;
  private int _i3;
  private int _k1Calculated = -1;
  /// <summary>
  /// True if the birth number belongs to a woman.
  /// </summary>
  public bool IsFemale { get; private set; }
  /// <summary>
  /// True if this is a D-Nummer.
  /// </summary>
  public bool IsDNr { get; private set; }
  /// <summary>
  /// True if this is a H-Nummer.
  /// </summary>
  public bool IsHNr { get; private set; }

  /// <summary>
  /// Constructor, loads the parameter into a local field.
  /// </summary>
  /// <param name="foedselsnummer"></param>
  public NorwegianBirthNumberChecker(string foedselsnummer)
  {
	 _fnr = foedselsnummer;
  }
  /// <summary>
  /// Starts the check of the loaded birth number.
  /// </summary>
  /// <param name="allowDNumber">
  /// True: D numbers will be adjusted to do a right date check.
  /// False: This method returns false if a D number is recognized.
  /// </param>
  /// <param name="allowHNumber">
  /// True: H numbers will be adjusted to do a right date check.
  /// False: This method returns false if a H number is recognized.
  /// </param>
  /// <returns></returns>
  public bool Check(bool allowDNumber, bool allowHNumber)
  {
	 if (!CheckNumbers())
	 {
		if (OnWrongCharacters != null) OnWrongCharacters(_fnr);
		return false;
	 }
	 if (!CheckLength())
	 {
		if (OnWrongLength != null) OnWrongLength(_fnr);
		return false;
	 }
	 CreateParts();
	 CreateDigits();
	 if (!CheckValidDate(allowDNumber, allowHNumber))
	 {
		if (OnWrongDate != null) OnWrongDate(_fnr);
		return false;
	 }
	 if (!CheckYearGreater1900())
	 {
		if (OnYearLess1900 != null) OnYearLess1900(_fnr);
		// NO RETURN! Fnr can be ok!
	 }
	 // Recognize sex
	 IsFemale = _i3 % 2 == 0;
	 if (IsFemale)
	 {
		if (OnFemaleRecognized != null) OnFemaleRecognized(_fnr);
	 }
	 else
	 {
		if (OnMaleRecognized != null) OnMaleRecognized(_fnr);
	 }
	 // Check the check digits k1 and k2
	 if (!CheckCheckNumber1())
	 {
		if (OnWrongCheckNumber1 != null) OnWrongCheckNumber1(_fnr);
		return false;
	 }
	 if (!CheckCheckNumber2())
	 {
		if (OnWrongCheckNumber2 != null) OnWrongCheckNumber2(_fnr);
		return false;
	 }
	 return true;
  }
  private void CreateParts()
  {
	 _day = _fnr.Substring(0, 2);
	 _month = _fnr.Substring(2, 2);
	 _year = _fnr.Substring(4, 2);
	 _individual = _fnr.Substring(6, 3);
	 _k1 = _fnr.Substring(9, 1);
	 _k2 = _fnr.Substring(10, 1);
  }
  private void CreateDigits()
  {
	 _d1 = Convert.ToInt32(_day.Substring(0, 1));
	 _d2 = Convert.ToInt32(_day.Substring(1, 1));
	 _m1 = Convert.ToInt32(_month.Substring(0, 1));
	 _m2 = Convert.ToInt32(_month.Substring(1, 1));
	 _y1 = Convert.ToInt32(_year.Substring(0, 1));
	 _y2 = Convert.ToInt32(_year.Substring(1, 1));
	 _i1 = Convert.ToInt32(_individual.Substring(0, 1));
	 _i2 = Convert.ToInt32(_individual.Substring(1, 1));
	 _i3 = Convert.ToInt32(_individual.Substring(2, 1));
  }
  private bool CheckNumbers()
  {
	 long fnr;
	 return Int64.TryParse(_fnr, out fnr);
  }
  private bool CheckLength()
  {
	 return _fnr.Length == 11;
  }
  private bool CheckValidDate(bool allowDNumber, bool allowHNumber)
  {
	 string date = _fnr.Substring(0, 6);
	 if (_fnr[0] > '3')
	 {
		IsDNr = true;
		if (OnDNumberRecognized != null) OnDNumberRecognized(_fnr);
		if (allowDNumber)
		   date = (_fnr[0] - '4') + _fnr.Substring(1, 5);
	 }
	 if (_month[0] > '3')
	 {
		IsHNr = true;
		if (OnHNumberRecognized != null) OnHNumberRecognized(_fnr);
		if (allowHNumber)
		   date = (_day + (_month[0] - '4') + _month[1] + _year);
	 }
	 // Both D and H number isn't allowed
	 if (IsDNr && IsHNr) return false;
	 DateTime tmp;
	 return DateTime.TryParseExact(date, "ddMMyy",
								   System.Globalization.CultureInfo.InvariantCulture,
								   System.Globalization.DateTimeStyles.None,
								   out tmp);
  }
  private bool CheckYearGreater1900()
  {
	 // this check is only valid for real fnr
	 if (IsDNr || IsHNr) return true;
	 // dersom individnummeret er mellom 500 og 750 er vedkommende født mellom 1855 og 1899
	 int i = Convert.ToInt32(_individual);
	 return !(i >= 500 && i < 750);
  }
  private bool CheckCheckNumber1()
  {
	 // no check for H numbers
	 if (IsHNr) return true;
	 // Calculate k1 (first check digit)
	 _k1Calculated = 11 - (((3 * _d1) + (7 * _d2) + (6 * _m1) + (1 * _m2) + (8 * _y1) + (9 * _y2) + (4 * _i1) + (5 * _i2) + (2 * _i3)) % 11);
	 _k1Calculated = (_k1Calculated == 11 ? 0 : _k1Calculated);
	 // k1 cannot be 10
	 if (_k1Calculated == 10) return false;
	 // Is calculated k1 the same as k1 in _fnr?
	 return _k1Calculated == Convert.ToInt32(_k1);
  }
  private bool CheckCheckNumber2()
  {
	 // no check for H numbers
	 if (IsHNr) return true;
	 if (_k1Calculated == -1)
	 {
		// Program error: the order in the public Check method is wrong!
		throw new Exception("Error in FoedselsNummerChecker: " +
							"The CheckCheckNumber1 method must be called BEFORE CheckCheckNumber2 starts! " +
							"This is a program error. Most possibly the order in the Check method is wrong.");
	 }
	 // Calculate k2 (second check digit)
	 int k2Calculated = 11 - (((5 * _d1) + (4 * _d2) + (3 * _m1) + (2 * _m2) + (7 * _y1) + (6 * _y2) + (5 * _i1) + (4 * _i2) + (3 * _i3) + (2 * _k1Calculated)) % 11);
	 k2Calculated = (k2Calculated == 11 ? 0 : k2Calculated);
	 // Fnr with k2 = 10 is invalid
	 if (k2Calculated == 10) return false;
	 // Is calculated k2 the same as k2 in _fnr?
	 return k2Calculated == Convert.ToInt32(_k2);
  }
  }
}

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...