F6 Observera att när man utvecklar program så är inte alla lösningar på vägen korrekta. Speciellt den här gången så finns många OH med program som inte fungerar eftersom det är just det vi skall se på här. På föreläsningen diskuteras just detta.! Från en färdig algoritm för problemet att bestämma kontrollsiffran i ett personnummer väljer vi datarepresentation och formulerar algoritmen i pseudokod. Slutligen kodar vi i Java! När vi går igenom exemplet ovan så går vi också igenom de flesta av Javas primitiver. Uppgift: Skriv ett program som beräknar kontrollsiffran till ett inmatat personnummer (9 siffror). På Skatteverkets hemsida finns personnummer noggrant beskrivna och där beskrivs algoritmen för att generera en kontrollsiffra. (2 sidor med kopia därifrån ej medtagna) Andra timmen så försöker vi kompilera och tolka felutskrifterna/rätta buggarna. Nästa gång: Att skriva egna klasser F6 1 F6 2 Algoritm för att beräkna kontrollsiffran i ett personnummer givet de 9 första siffrorna. 1. Siffrorna i födelseår, -mån, -dag och -nummer multipliceras växelvis med 2 och 1. (dvs multiplicera 1:a, 3:e, 5:e, 7:e och 9:e siffrorna med 2) 2. Lägg samman siffrorna i produkterna. OBS! 12 räknas som 1+2. (dvs addera siffrorna (inte talen) som erhölls i steg 1 samt 2:a, 4:e, 6:e och 8:e siffrorna) 3. Entalssiffran i siffersumman dras från talet 10. 4. Restsiffran blir kontrollsiffra. Är resten 10, blir kontrollsiffran 0. (alltså : 10 summa%10 om 10 ändra till 0 Pseudokod Torrsimning av algoritm för personnummer // multiplicera 1:a, 3:e, 5:e, 7:e och 9:e siffrorna med 2 // addera siffrorna (inte talen) som erhölls i steg 1 samt 2:a, 4:e, 6:e och 8:e siffrorna // Entalssiffran i siffersumman dras från talet 10. // Restsiffran blir kontrollsiffra. Är resten 10 blir kontrollsiffran 0. 760308-415x 7 6 0 3 0 8 4 1 5 2 1 2 1 2 1 2 1 2 14 6 0 3 0 8 8 1 10 1+4+6+0+3+0+8+8+1+1+0 = 32 10-summa%10 = 10-2 = 8 (% är javas mod operator dvs den ger resten vid division med ) F6 3 F6 4
Pseudokod int berkontsiffra(personnummer pnr) // multiplicera 1:a, 3:e, 5:e, // 7:e och9:e siffrorna med 2 for alla udda index i i pnr loop (1) pnr(i) = pnr(i)*2 // addera siffrorna (inte talen) som // erhölls i steg 1 samt 2:a, 4:e, // 6:e och 8:e siffrorna for alla index i i pnr loop (2) summa = summa + pnr(i)/10+ pnr(i)%10 // kontrollsiffra= Entalssiffran i // siffersumman dras från talet 10. // Är resten 10 blir kontr.siffran 0 tmp = (10 summa%10); (3) if (tmp == 10) { return 0; else { return tmp; end beräknakontsiffra Jobba med lösningen Lämpligt att slå ihop de två första looparna? fortfarande pseudokod for alla index i i pnr loop (1+2) if udda(i) then else tmp = 2*pnr(i) summa = summa + tmp/10 + tmp%10 summa = summa + pnr(i) end if Hur representera ett personnummer? Låt pnr vara ett fält. Tekniska detaljer: Fält indexeras alltid från 0 så udda(i) skall bytas mot!udda(i) eller också får man byta plats på if-alternativen. F6 5 F6 6 Förenkla det sista (pseudokod) Flera möjliga alternativ: 10 - entalssiffran i summa funkar nästan men inte när summa är delbar med 10 för då får vi 10-0 = 10 och det skall vara 0 tmp = (10 summa%10); (3) if (tmp == 10) { return 0; else { return tmp; Vi kan testa med if sats (enl. ovan) eller return (10 summa%10)%10 (3) sista mod satsen behövs när parentesen blir 10 och det blir den när summa%10 = 0 Ytterligare ett alternativ: for i in 0..9 loop (3) if (i+summa)%10 == 0 then return i end if end for det finns många lösningar även på enkla problem... F6 7 Java * Beräknar kontrollsiffran i ett * personnummer utgående från * de första 9 siffrorna ********* ********** ********** int berkontrollsiffra (int[] pnr) { int tmp = 0; for (int i = 0; i < 9; i=i+1) { if ( odd(i) ) { summa = summa + pnr[i]; else { tmp = 2*pnr[i]; summa = summa + tmp/10 + tmp%10; // end if // return ((10 - summa%10)%10); // end berkontrollsiffra Behövs felkontroll? tex att pnr är 9 st entalssiffror ( i en int kan man ju ha tex -3 eller 45 ) och inte fler/färre tex 7 tal? Observera att index går från 0 i fältet F6 8
Odd * Undersöker om parametern 'tal' * är udda. I så fall returneras true * annars returneras false ********** ********** ********** static boolean odd(int tal) { if (tal%2!= 0) { return true; else { return false; // end odd // ---------- ---------- ---------- När man förstått hur booleaner fungerar så byter man alltid ut if-satsen mot: return (tal%2!= 0); eller return!(tal%2 == 0); Nu behöver vi en struktur för hela programmet. import x.y.*; Programstruktur: allmänt // annat som behövs * Purpose : Vad gör programmet * Author : Vilka har gjort det, Namn * Group : Labgruppsnummer * Assignment : Labnummer och ev deluppg. * Last changed: Sista ändring ********** ********** ********** public class NamnXxxx { // deklaration av variabler // deklaration av metoder * En förklaring till vad metoden gör [public][static] typ namn([typ parameter,...]){ <...> // end namn public static void main(string[] args){ // deklarationer av lokala variabler // satser // end main // end NamnXxxx F6 9 F6 10 Programstruktur: vårt exempel /* javadoc kommentaren om programmet, se ovan. public class Pnrkontroll { * Odd undersöker om 'tal' är udda. public static boolean odd(int tal) { // end odd * berkontrollsiffra beräknar kontrollsiffran. public static int berkontrollsiffra (int[] pnr) { // end berkontrollsiffra // ========== ========== ========== public static void main(string[] args){ // end main // end Pnrkontroll F6 11 Huvudprogram (main) pseudokod // skapa ett fält // läs in 9 siffror // läs en siffra 9 gånger // anropa berkontrollsiffra // skriv ut resultatet Klassen java.util.scanner förser oss med inmatningsprimitiver så vi kan läsa tokens från tangentbordet: import java.util.*;... while(in.hasnext()) { System.out.println(in.next()); Metoder i Scanner: (ersätt X med Int, Double,..., eller inget) in.hasnextx() finns det ett X in.nextx() ger nästa X in.nextline() ger hela raden som en String F6 12
Huvudprogram (main) public static void main (String[] args) { // skapa ett fält // läs in 9 siffror System.out.print ("Ange de 9 första siffrorna: "); // läs en siffra 9 gånger // TODO finns det nåt att läsa? pnr1to9[i] = in.nextint(); // // anropa berkontrollsiffra och // skriv ut resultatet System.out.print("K-siffran är: "); System.out.println (berkontrollsiffra(pnr1to9)); // end main // end Pnrkontroll Ingen felkontroll ännu och inga garantier för att allt är rätt... main public static void main (String[] args){ System.out.print( "Ange de 9 forsta siffrorna: "); if (in.hasnext()) { pnr1to9[i] = in.nextint(); --> // utskrift av det inlästa System.out.println("i= " + i + " **= " + pnr1to9[i]); // System.out.print("K-siffran är: "); System.out.println( berkontrollsiffra(pnr1to9)); // end main OBS: Här finns fortfarande flera buggar som vi rättar nästa timme. F6 13 F6 14 import java.util.*; // fungerande program utan buggar //* Purpose: Kontrollerar sista siffran i ett personnummer //* Author: Erland Holmström //* Group: - //* Assignement: OH bilder //* Last changed: 09-10-25 public class Pnrkontroll { ********** * Undersöker om parametern 'tal' är udda. * Isåfall returneras true annars returneras false ********** ********** ********** ********** static boolean odd(int tal) { return (tal%2!= 0); // end odd /* ********** ********** ********** ********* * Beräknar kontrollsiffran i ett personnummer utgående * från de första 9 siffrorna i ett personnummer. ********** **r******** ********** ********** static int berkontrollsiffra(int[] pnr1to9) { int tmp = 0; for (int i = 0; i <= 8; i++) { if (odd(i)) { summa = summa + pnr1to9[i]; else { tmp = 2*pnr1to9[i]; summa = summa + tmp/10 + tmp%10; return ((10 - summa%10)%10); // end berkontrollsiffra /* ********** ********** ********** ********** ********* // Felhantering saknas public static void main(string[] args) { System.out.print("Ange de 9 forsta siffrorna: "); if (in.hasnext()) { String str = in.nextline(); if ( str.length() == 9 ) { pnr1to9[i] = Character.digit(str.charAt(i), 10); else { System.out.println ("main: to many or to few numbers"); else { System.out.println("no indata"); System.out.print("Kontrollsiffran är: "); System.out.println(berKontrollSiffra(pnr1to9)); // end main // end Pnrkontroll --------------------------------------- Nästa OH bild om slumptal i Java har inget med exemplet ovan att göra utan det råkade finnas plats här (ifall ni vill skapa slumptal för tex labben). Vi återkommer till slumptal senare. F6 15 F6 16
Math.random() I klassen java.lang.math finns metoden public static double random() Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range. double x = Math.random() ger alltså ett tal i intervallet 0.0 <= x < 1.0 Antag att vi vill ha tal mellan 1-4 inklusive double slump = 4*Math.random() Också vill vi ha ett heltal så vi typomvandlar (type cast) int slump = (int)(4*math.random()) Nu får vi 0<=slump<=3... = (int)(4*math.random()+1.0) Nu får vi 1<=slump<=4 (Jämför också med klassen java.util.random) F6 17