Lunds universitet FYTA11 Institutionen för Astronomi och Teoretisk fysik HT 14 Lösningsförslag FYTA11 Javaprogrammering Torsdag 29 januari 2015, 09:15 13:15 Instruktioner Hjälpmedel: Papper och penna. Behandla högst en uppgift per papper och sätt ditt namn och uppgiftens nummer på varje papper. Skriv läsligt och kommentera utförligt vad du gör det kan ge dig poäng även om resultatet blir fel. Tentamen omfattar fyra uppgifter som vardera kan ge upp till tio poäng. För G och VG krävs 20 respektive 30 poäng, inräknat de högst fem bonuspoängen från simuleringsövningarna.
Uppgift 1: Små fel Korrigera felen i följande kodstycken där felens natur anges av kommentarer i/efter koden. Skriv en korrekt version av raden/raderna som ändras (och tänk på att det kan behöva framgå vilken rad det rör sig om). a. b. c. d. e. f. int tries = 10; //for(int try = 0; try < tries; ++try) // error: not a statement for(int t = 0; t < tries; ++t) // "try" är reserverat ord trysomething(); //int ints[12] = new int[12]; int[] ints = new int[12]; // alternativt: int ints[] =... // error: ] expected // error: illegal start of expression //public static void square(double x) public static double square(double x) // returtyp return x * x; // cannot return a value from method whose result type is void int max = 12; //System.out.println((int)Math.random()*max); System.out.println((int)(Math.random()*max)); // Skriver alltid ut 0 /* set initial width and height to 3 */ //int width = height = 3; int width = 3, height = 3; // error: cannot find symbol /* i en konstruktor i ett grafiskt program */ ActionListener a = new ActionListener() // void actionperformed(actionevent ae) /*... */ // <- här public void actionperformed(actionevent ae) /*... */ ; // error: actionperformed(actionevent) in <anonymous Test$1> cannot // implement actionperformed(actionevent) in ActionListener // attempting to assign weaker access privileges; was public
g. public class Test /* Constructor */ // public void Test(int value) <- felet var dock här public Test(int value) this.value = value; public void print() System.out.println(value); private int value; public static void main(string[] s) Test t = new Test(42); <- felet pekar på denna rad t.print(); // constructor Test in class Test cannot be applied to given types // required: no arguments // found: int h. i. public static void main(string[] s) // if(s.length == 0 s[0] == "help") if(s.length == 0 s[0].equals("help")) // 1: 2: equals System.out.println("please give one argument"); // Dubbelfel: // Fel 1: programmet krashar med ArrayIndexOutOfBoundsException // om man kör det utan argument // Fel 2: programmet skriver inte ut hjäptexten om man ger "help" // som argument på kommandoraden try Integer.parseInt(s[0]); // catch(e) // error: <identifier> expected catch(exception e) System.out.println("exception!");
Uppgift 2: Magiska kvadrater En äkta magisk kvadrat av ordning n är en kvadrat bestående av n 2 rutor ifyllda med heltalen 1 till n 2 på så sätt att varje kolumn och rad och de båda diagonalerna bildar samma summa, M(n) = 1 2 (n3 +n). Se figur. Din uppgift är att skriva en metod som avgör om dess input är en magisk kvadrat. Metodens signatur är static boolean ismagicsquare(int[][] sq) där sq beskriver en kvadrat av storlek n n. Om någon av raderna (eller kolumnerna beroendepåvilken tolkning viväljer) isqinteharrätt antalelement så skall metoden returnera false. Annars skall metoden returnera true om och endast om alla tal från 1 till n 2 förekommer i kvadraten och samtliga rad-, kolumn- och diagonalsummor är M(n). Metoden är tänkt att vara användbar för ganska stora kvadrater, exempelvis n = 3000. Tänk på vad detta innebär för hur M(n) representeras. Dessutom bör tids- och minnesåtgången inte skala sämre än n 2.
public static boolean ismagicsquare(int[][] sq) int n = sq.length; // För att kolla så alla n*n tal förekommit boolean[] seen = new boolean[n * n + 1]; // Kolla så det är en kvadrat med unika tal 1...n*n for(int i = 0; i < n; ++i) if(sq[i] == null sq[i].length!= n) return false; for(int j = 0; j < n; ++j) int v = sq[i][j]; if(v < 1 v > n*n seen[v]) return false; // Räkna ut M(n). Notera long för att klara stora n long m = ((long)n * n * n + n) / 2; // Summorna längs diagonalerna long diasum1 = 0, diasum2 = 0; for(int i = 0; i < n; ++i) // Summa i rad och kolumn long rowsum = 0, colsum = 0; for(int j = 0; j < n; ++j) rowsum += sq[i][j]; colsum += sq[j][i]; if(rowsum!= m colsum!= m) return false; diasum1 += sq[i][i]; diasum2 += sq[i][n-1 - i]; if(diasum1!= m diasum2!= m) return false; return true; // testfall: // int[][] a = 2,7,6, 9,5,1, 4,3,8; // System.out.println(isMagicSquare(a));
Uppgift 3: Fakultet Produktenavallapositivatalmindreän,ellerlikamedettgivettalnkallasn-fakultet och skrivs n!. Fakulteten kan definieras rekursivt enligt: n! = (n 1)! n, 1! = 1, 0! = 1. Skriv en klass med en rekursiv metod som, givet ett heltal av typen long, returnerar fakulteten för detta heltal. Om argumentet är negativt eller för stort skall ett exception av klasserna NegativeFactorialException respektive LargeFactorialException genereras. Det största möjliga heltalet ges av klassvariabeln MAX_VALUE i klassen Long, så om fakulteten (n 1)! redan är uträknad så vet vi att argumentet n är för stort om (n 1)! är större än MAX_VALUE dividerat med n. public class FactorialException extends Exception public FactorialException(String what) super(what); public class NegativeFactorialException extends FactorialException public NegativeFactorialException() super("negative argument to Factorial."); public class LargeFactorialException extends FactorialException public LargeFactorialException() super("too large argument to Factorial."); Lösning: se uppgift 4.
Uppgift 4: Fakultet igen Lägg till en main-metod i klassen från den förgående uppgiften. Denna metod skall för varje kommandoradsargument till programmet skriva ut fakulteten för motsvarande tal. Om ett argument inte är ett tal skall ett felmeddelande skrivas ut, men resterande argument behandlas som vanligt. Om ett tal får metoden från föregående uppgift att kasta ett exception skall motsvarande felmeddelande skrivas ut; minns att Exception har metoden string getmessage(). Ett exempel: $ java Factorial 10 apa -1 100 17 10! = 3628800 ERROR: apa is not an integer. ERROR: -1 Negative argument to Factorial. ERROR: 100 Too large argument to Factorial. 17! = 355687428096000 Följande metod i klassen Long kan vara till nytta: public class Long /** Returns a double value initialized to the value represented * by the specified String. * @param s the string to be parsed. * @return the double value represented by the string argument. * @throws NumberFormatException if the string does not contain * a parsable double. */ public static long parselong(string s) throws NumberFormatException; //...
// Lösning till uppgift 3 public class Factorial public static long factorial(long n) throws FactorialException if(n < 0) throw new NegativeFactorialException(); if(n <= 1) return 1; long nm1 = factorial(n-1); if(nm1 > Long.MAX_VALUE / n) throw new LargeFactorialException(); return n*nm1; // Lösning till uppgift 4 public static void main(string[] args) for(int i = 0; i < args.length; ++i) try long f = factorial(long.parselong(args[i])); System.out.println(args[i] + "! = " + f); catch(factorialexception e) System.out.println("ERROR: " + args[i] + " " + e.getmessage()); catch(numberformatexception e) System.out.println("ERROR: " + args[i] + " is not an integer.");