Avatar billede hsx Nybegynder
29. november 2004 - 13:52 Der er 13 kommentarer

Hjælp til et java program som checker CPR v hj. a. Modulus 11

Hej

Hvem kan hjælpe med at lave en java Class file som checker et CPR nummers gyldighed efter Modulus 11 metoden efter følgende regler:

CPR nummer eksempel: 1711968535
> 1*4+7*3+1*2+1*7+9*6+6*5+8*4+5*3+3*2+5*1 = 176
> 176 modulus 11 = 0
> CPR nummer er ok.
>
Hilsen Henrik
Avatar billede rasmusbg Nybegynder
29. november 2004 - 14:11 #1
Vil du have kildekoden til en klasse, eller mere en slags vejledning?
Avatar billede arne_v Ekspert
29. november 2004 - 14:39 #2
Jeg lavede engang den her klasse:

import java.util.*;

public class CPR {
  // format of danish CPR number:
  //  ddmmyy-nnnc
  // where:
  //  dd  = day
  //  mm  = month
  //  yy  = year
  //  nnn = sequence (includes century)
  //  c  = checksum (includes sex)
  private String number;

  // constructor
  public CPR(String number) {
      this.number = number;
  }

  // check validity
  public boolean isValid() {
      int[] ix = { 0, 1, 2, 3, 4, 5, 7, 8, 9, 10 };
      int[] c = { 4, 3, 2, 7, 6, 5, 4, 3, 2, 1 };
      if (number.length() != 11) {
        return false;
      }
      if (number.charAt(6) != '-') {
        return false;
      }
      for (int i = 0; i < 10; i++) {
        if (!Character.isDigit(number.charAt(ix[i]))) {
            return false;
        }
      }
      if (dd() > 31) {
        return false;
      }
      if (mm() > 12) {
        return false;
      }
      if (century() == 0) {
        return false;
      }
      int temp = 0;
      for (int i = 0; i < 10; i++) {
        temp = temp + c[i] * numericValue(number.charAt(ix[i]));
      }
      return ((temp % 11) == 0);
  }
  // check make/female
  public boolean isMale() {
      return odd(numericValue(number.charAt(10)));
  }
  public boolean isFemale() {
      return even(numericValue(number.charAt(10)));
  }
  // get date of birth
  public Date getBirth() {
      int year = yy() + century();
      int mon = mm() - 1;
      int mday = dd();
      GregorianCalendar temp = new GregorianCalendar();
      temp.set(year, mon, mday);
      return temp.getTime();
  }
  // get age
  public int getAge() {
      Calendar now = GregorianCalendar.getInstance();
      Calendar born = new GregorianCalendar();
      born.setTime(getBirth());
      int result;
      result = now.get(Calendar.YEAR) - born.get(Calendar.YEAR);
      if (now.get(Calendar.DAY_OF_YEAR) < born.get(Calendar.DAY_OF_YEAR)) {
        result--;
      }
      return result;
  }

    // standard methods
    public int hashCode() {
        return number.hashCode();
    }
    public boolean equals(Object o) {
        if(o instanceof CPR) {
            return number.equals(((CPR)o).number);
        } else {
            return false;
        }
    }
  // get parts
  private int dd() {
      return Integer.parseInt(number.substring(0, 2));
  }
  private int mm() {
      return Integer.parseInt(number.substring(2, 4));
  }
  private int yy() {
      return Integer.parseInt(number.substring(4, 6));
  }
  // calculate century
  private int century() {
      switch (numericValue(number.charAt(7))) {
        case 0 :
        case 1 :
        case 2 :
        case 3 :
            return 1900;
        case 4 :
        case 9 :
            if (yy() < 37)
              return 2000;
            else
              return 1900;
        case 5 :
        case 6 :
        case 7 :
        case 8 :
            if (yy() < 37)
              return 2000;
            else if (yy() > 57)
              return 1800;
            else
              return 0;
        default :
            return 0;
      }
  }
  // odd/even
  private static boolean odd(int v) {
      return ((v & 1) == 1);
  }
  private static boolean even(int v) {
      return ((v & 1) == 0);
  }
  // numeric value of char
  private static int numericValue(char c) {
      return (c - '0');
  }
}
Avatar billede rasmusbg Nybegynder
29. november 2004 - 14:43 #3
Øj...du godeste! Sikken en masse kode :)

Det kan godt være min udgave er en gang halvvejs slamkode, men noget mindre fylder det ;)

import java.math.*;

public class Matematik {

public Matematik() {
}
/**
* @return boolean - om cpr-nr'et er gyldigt
* Dette gælder både, om det er en gyldig dato og om modulo 11 testen er opfyldt
*/
public static boolean cprTest(String cpr) {
    int checksum = 0;
    BigInteger nummer = new BigInteger(cpr);
    BigInteger temp = nummer.divide(new BigInteger("1000000"));
    boolean legalDate = false;
    int k = temp.remainder(new BigInteger("100")).intValue();
    switch(k) {
        case 1: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("32")) == -1) legalDate = true;
                break;
        case 2: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("29")) == -1) legalDate = true;
                break;
        case 3: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("32")) == -1) legalDate = true;
                break;
        case 4: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("31")) == -1) legalDate = true;
                break;
        case 5: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("32")) == -1) legalDate = true;
                break;
        case 6: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("31")) == -1) legalDate = true;
                break;
        case 7: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("32")) == -1) legalDate = true;
                break;
        case 8: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("32")) == -1) legalDate = true;
                break;
        case 9: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("31")) == -1) legalDate = true;
                break;
        case 10: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("32")) == -1) legalDate = true;
                break;
        case 11: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("31")) == -1) legalDate = true;
                break;
        case 12: if (temp.divide(new BigInteger("100")).compareTo(new BigInteger("32")) == -1) legalDate = true;
                break;
        default: legalDate = false;
    }
    for (int i = 9; i >= 7; i--) {
        checksum += ((nummer.divide(new BigInteger((""+(long)Math.pow(10,i))))).remainder(new BigInteger("10")).intValue())*(i-5);
    }
    for (int i = 6; i >= 0; i--) {
        checksum += ((nummer.divide(new BigInteger(""+(long)Math.pow(10,i)))).remainder(new BigInteger("10")).intValue())*(i+1);
    }
    if (checksum%11 == 0 && legalDate) return true;
    return false;
}
}
Avatar billede arne_v Ekspert
29. november 2004 - 14:47 #4
Koden gør meget andet. Selve modulus 11 checket ligger i de her linier:

      int[] ix = { 0, 1, 2, 3, 4, 5, 7, 8, 9, 10 };
      int[] c = { 4, 3, 2, 7, 6, 5, 4, 3, 2, 1 };

      ...

      int temp = 0;
      for (int i = 0; i < 10; i++) {
        temp = temp + c[i] * numericValue(number.charAt(ix[i]));
      }
      return ((temp % 11) == 0);
Avatar billede rasmusbg Nybegynder
29. november 2004 - 14:52 #5
Det kan jeg godt se. Håber det er iorden, at jeg stiller et enkelt spørgsmål:

Hvordan kan det være, at du ikke har lavet en gender()-metode i stedet for både en isFemale()- og en isMale()-metode?
Avatar billede arne_v Ekspert
29. november 2004 - 14:57 #6
Nu er det 4 år siden jeg skrev den kode, så jeg kan ikke huske hvorfor.

Gæt: jeg ville undgå nogle konstanter.

if(cpr.isMale()) {

versus

if(cpr.gender() == CPR.MALE) {
Avatar billede rasmusbg Nybegynder
29. november 2004 - 15:02 #7
Ja, man risikerer nemt, at det bliver noget rod, hvis man har mange konstanter. At du så lavede en metode til begge køn, må være et udslag af politisk korrekthed (eller fuldstændighed)...det kan da ikke lade sig gøre, at være intet-/fælles-køn i cpr-systemet ;D
Avatar billede hsx Nybegynder
29. november 2004 - 20:38 #8
Det er koden, jeg gerne vil have. Arne.V's kode kan jeg ikke få til at køre. Fejlmeddelelsen er Exception i thread "main" java.lang.NoSuchMethodError. Hvad gør jeg
Avatar billede arne_v Ekspert
29. november 2004 - 20:47 #9
Hvordan ser din test klasse ud ?

Den her virker fint hos mig:

public class TestCPR {
    public static void main(String[] args) {
        CPR cpr = new CPR("123456-7890");
        System.out.println(cpr.isValid());
    }
}
Avatar billede arne_v Ekspert
12. december 2004 - 19:33 #10
OK ?
Avatar billede arne_v Ekspert
01. januar 2005 - 14:05 #11
??
Avatar billede hsx Nybegynder
03. januar 2005 - 09:02 #12
Tak for hjælpen - Jeg har fået koden til at virke i en opgave der blev afleveret i ugen før jul. Da jeg ikke er særlig sikker ud i java programmering tog det noget tid at finde ud af, men det lykkedes.

Tak endnu engang og godt nytår
Avatar billede arne_v Ekspert
03. januar 2005 - 10:11 #13
Selv godt nytår.

Pointen var nu at hvis alt er afklaret, så skulle du afslutte spørgsmålet
ved at acceptere et svar !
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester