L?sningsforslag ukeoppg. 2:  6. - 10. sep (INF1000 - H?st 2010)

Variabler og uttrykk (kap. 2.3 - 2.6), terminal I/O (kap. 3.1-3.5), if-setninger og l?kker (kap. 4.1 - 4.4), og litt om arrayer (kap. 5.1 - 5.2)

NB! Legg merke til at disse er l?sningsforslag.  L?sningene dine trenger ikke ? v?re like med disse forslag for ? v?re riktige.  Det er vanlig i programmering at samme oppgave kan l?ses p? mange vidt forskjellige m?ter, og alle fremgangsm?ter er ok i INF1000 s? lenge de leder fram til riktig resultat og oppfyller kravene som st?r i oppgaveteksten.

M?l: ?ve p? bruk av variable og uttrykk av forskjellige typer (int, double, og boolean), innlesing og utskrift til terminal, if-setninger, l?kker, og en liten oppgave med array.

Oppgaver til teoritimen

  1. Presedensregler ― i hvilken rekkef?lge utf?res regneoperasjonene?
    Avgj?r i hvert av disse tilfellene, uten ? bruke datamaskin, hvilken verdi som blir skrevet ut p? skjermen.

    For ? svare p? denne oppgaven m? du kjenne reglene for evaluering (utregning) av numeriske uttrykk i Java. Kortversjonen av disse er at uttrykk beregnes fra venstre mot h?yre, men multiplikasjoner og divisjoner utf?res f?r addisjoner og subtraksjoner. Du kan lese mer om dette p? side 37 i l?reboka.
      1.  System.out.println(3 * 4 + 5);           // 17
      2.  System.out.println(3 + 4 * 5);           // 23
      3.  System.out.println((3 + 4) * 5);         // 35
      4.  System.out.println(1 / 2 * 5);           // 0
      5.  System.out.println(1 / 2 * 5.0);         // 0.0
      6.  System.out.println(1.0 / 2 * 5);         // 2.5
      7.  System.out.println(4 * 2 * 2 * 1);       // 16
      8.  System.out.println(4 / 2 / 2 / 1);       // 1   |< Unng? slike uttrykk!,
      9.  System.out.println(5 * 4 / 3 * 2 / 1);   // 12  |< bruk heller parenteser!
    
    Hvis du ?nsker mer info kan du se f?lgende oversikt med presedens for alle operatorene. Jo h?yere oppe p? denne lista operatoren st?r jo f?r blir den utf?rt, mens de som st?r p? samme niv? er likestilt og utf?res fra venstre til h?yre. Tabellen er tatt fra www.janeg.ca/scjp/oper/precedence.html, og er basert p? side 378 i The Java Programming Language:
    Operator type Operators
    Postfix [] . (params) expr++ expr--
    Unary ++expr --expr +expr -expr ~ !
    Creation or Cast new (type)expr
    Multiplicative * / %
    Additive + -
    Shift << >> >>>
    Relational < > >= <= instanceof
    Equality == !=
    Bitwise AND &
    Bitwise exclusive OR ^
    Bitwise inclusive OR |
    Logical AND &&
    Logical OR ||
    Ternary ?:
    Assignment = += -= *= /= %= >>= <<= >>>= &= ^= |=

  2. Logiske uttrykk: (tabell 2.5, side 39)
    Avgj?r hvilken verdi den boolske variabelen b f?r etter hver av disse tilordningssetningene, n?r vi antar at heltallsvariablene x, y, og z har f?tt verdier som f?lger: int x = 3, y = 4, z = 1;
      1.  b = (x < y) && (y < z);        // false
      2.  b = (x < y) || (y < z);        // true
      3.  b = ! (x < y);                 // false
      4.  b = x < y;                     // true
      5.  b = x <= y;                    // true
      6.  b = (x == y);                  // false
      7.  b = (x != y);                  // true
    
    Hint: Eksempel p? hvordan man kan bruke slike boolske uttrykk i et program:
        int x = 3, y = 4, z = 1;
        if ((x < y) && (y < z)) {
            System.out.println("Det stemmer at x < y < z."); // Blir dette skrevet ut?
        }
    


  3. Innlesing fra terminal: kap. 3, oppg. 3 (side 70)
    Lag et program som ber om og leser inn to flyttall. Programmet skal deretter regne ut produktet av de to tallene og skrive ut svaret. Her er et eksempel p? hvordan en kj?ring av programmet kan se ut:
     Oppgi verdien til x: 9
     Oppgi verdien til y: 10
     Produktet av x og y er 90.0
    
    Hint: F?lg malen fra eksemplet p? side 56.  Innlesing fra terminal b?r gj?res i to steg, f?rst en utskrift som sier til bruker hva hun skal taste inn (det kalles for ledetekst), og s? kommer selve setningen som henter input fra tastaturet.  Bruk her tast.inDouble() og ikke tast.inInt().  Disse stopper kj?ringen av programmet inntil bruker har tastet inn et svar.  N?r bruker har gjort det, blir tallet lagret i den angitte variabelen, og kj?ringen av programmet fortsetter med neste setning.
    L?sningsforslag:
    Opprett filen Produkt.java med f?lgende linjer som innhold:
    import easyIO.*;
    class Produkt {
        public static void main(String[] args) {
    	In tast = new In();
    	Out skjerm = new Out();
    
    	skjerm.out("Oppgi verdien til x: ");
    	double x = tast.inDouble();
    
    	skjerm.out("Oppgi verdien til y: ");
    	double y = tast.inDouble();
    	
    	double produkt = x * y;
    	skjerm.outln("Produktet av x og y er: " + produkt);
        }
    }
    KJ?REEKSEMPEL:
    > java Produkt
    Oppgi verdien til x: 9.123
    Oppgi verdien til y: 10
    Produktet av x og y er: 91.22999999999999


    KOMMENTAR:
    Grunnen til at det ikke blir n?yaktig 91.23 er at Java internt lagrer slike double-verdier i det bin?re tallsystemet, som ikke kan representere helt n?yaktig visse desimalsifre etter komma.  N?r s? Java konverterer tilbake til det desimale tallsystemet ved utskrift, s? kan det derfor bli sm? feil som vist over.  To l?sninger p? dette er vist i neste oppgave.


  4. Utskrift med 2 desimaler p? to m?ter: easyIO og printf
    Ved utskrift av desimaltall er det ofte ?nskelig ? kontrollere hvor mange desimaler som skrives ut. Bruker vi System.out.println(tall) til ? skrive ut en double-variabel tall, f?r vi med alle desimalene som er lagret i tall (med unntak av avsluttende nuller i desimalene). To m?ter ? kontrollere antall desimaler som skrives ut er:

    • printf: I nyere versjoner av Java (5.0 og 6, ogs? kalt 1.5 og 1.6) finnes en metode som gir oss god kontroll over utskriften. Hvis vi skriver:
        System.out.printf("Tall: %.2f\n", tall);
      s? f?r vi skrevet ut verdien i variabelen tall med 2 desimaler, og hvis vi skriver:
        System.out.printf("Tall: %7.2f\n", tall);
      s? f?r vi skrevet ut tall p? 7 plasser (eller s? mange som er n?dvendig) og med 2 desimaler. Om n?dvendig fyller Java p? med blanke tegn til venstre slik at hele utskriften tar 7 plasser.  Koden \n (omvendt-skr?strek etterfulgt av n) gir et linjeskift, og kan tas bort i setningene over hvis du ikke ?nsker linjeskift.  Flere eksempler p? bruk av printf kan du se her (PDF) [Y.D. Liang "Introduction to Java Programming" 5. utg., side 64], og p? Wikipedia.

    • easyIO: Pakken easyIO gir tilsvarende resultat med f?lgende setninger:
        skjerm.outln(tall, 2);
        skjerm.outln(tall, 2, 7);
      For ? kunne bruke dette m? programmet ha setningnen "import easyIO.*;" ?verst, og setningen "Out skjerm = new Out();" plassert p? et passende sted i programmet f?r de ovennevnte skjerm.outln()-linjene, se eksemplet p? side 50 i l?reboka.  I tillegg m? easyIO v?re installert p? datamaskinen (mer om dette kommer p? bloggen). For info om andre muligheter for formatert utskrift med easyIO se oversikten p? side 52.  Ledeteksten "Tall: " kan skrives ut vha. en egen skjerm.out("Tall: ")-setning som du kan plassere f?r de ovennevnte skjerm.outln-setningene.
    Oppgave: Bruk dette til ? endre programmet fra forrige oppgave (i punkt 3. ovenfor) til ? skrive ut produktet med 2 desimaler, og igjen med 3 desimaler p? 10 plasser.
    import easyIO.*;
    class Produkt2 {
        public static void main(String[] args) {
    	In tast = new In();
    	Out skjerm = new Out();
    	double x;
    	double y;
    	double produkt;
    
    	skjerm.out("Oppgi verdien til x: ");
    	x = tast.inDouble();
    
    	skjerm.out("Oppgi verdien til y: ");
    	y = tast.inDouble();
    	
    	produkt = x * y;
    
    	// easyIO:
    	skjerm.out("Produktet av x og y er: ");
    	skjerm.out(produkt, 2);
    	skjerm.out(" = ");
    	skjerm.outln(produkt, 3, 10);
    
    	// printf:
    	skjerm.out("Produktet av x og y er: ");
    	System.out.printf("%.2f", produkt);
    	System.out.printf(" = %10.3f\n", produkt);
        }
    }
    
    KJ?REEKSEMPEL:
    > java Produkt2
    Oppgi verdien til x: 9.123
    Oppgi verdien til y: 10
    Produktet av x og y er: 91.23 =     91.230
    Produktet av x og y er: 91.23 =     91.230
    


  5. Beregning av skatt i Ruritania: kap. 4, oppg. 2 (side 82)
    I det fiktive landet Ruritania er skattereglene slik at hvis en person har inntekt < 10 000, s? betaler man 10% skatt p? hele inntekten, og hvis inntekten ≥ 10 000, s? betaler man 10% skatt p? de f?rste 10 000 kronene og 30% skatt p? resten av inntekten.  Lag et program som regner ut og skriver ut hvor mange kroner som skal betales i skatt.  Programmet skal lese inntekten (som antas ? v?re et desimaltall) fra terminal.
    import easyIO.*;
    
    class Skatt {
        public static void main (String[] args) {
    	In tast = new In();
            double inntekt;
    	double skatt;
    
    	System.out.print("Angi inntekt: ");
    	inntekt = tast.inDouble();
    
    	if (inntekt < 10000) {
    	    skatt = inntekt * 0.10;
    	} else {
    	    skatt = (10000 * 0.10) + (inntekt - 10000) * 0.30;
    	}
    
    	System.out.println("Skatten blir: " + skatt);
        }
    }
    
    KJ?REEKSEMPEL:
    > java Skatt
    Angi inntekt: 11000
    Skatten blir: 1300.0
    


  6. For-l?kke: kap. 4, oppg. 4 (side 83)
    Lag et program som skriver ut p? skjermen omkretsene til sirkler med radiusene r = 1, 2, ..., 10 (omkretsen O beregnes etter formelen O = 2 π r.  Sett π = 3.14).  Utskriften skal f?lge m?nsteret:
    Radius = 1 gir omkrets = 6.28
    Radius = 2 gir omkrets = 12.57
    ..osv..
    
    import easyIO.*;
    
    class Omkrets1 {
        public static void main(String[] args) {
            Out skjerm = new Out();
            double omkrets;
    
            for (int radius = 1; radius <= 10; radius++) {
                omkrets = 2.0 * 3.14 * radius;
                skjerm.out("Radius = " + radius + " gir omkrets = ");
                skjerm.outln(omkrets, 2);
            }
        }
    }
    
    KJ?REEKSEMPEL:
    > java Omkrets
    Radius = 1 gir omkrets = 6.28
    Radius = 2 gir omkrets = 12.57
    Radius = 3 gir omkrets = 18.85
    Radius = 4 gir omkrets = 25.13
    Radius = 5 gir omkrets = 31.42
    Radius = 6 gir omkrets = 37.70
    Radius = 7 gir omkrets = 43.98
    Radius = 8 gir omkrets = 50.27
    Radius = 9 gir omkrets = 56.55
    Radius = 10 gir omkrets = 62.83
    


  7. While-l?kke: (b): kap. 4, oppg. 5 (side 83)
    (a) Gjenta forrige oppgave, men bruk while-l?kke i stedet.
    import easyIO.*;
    class Omkrets2 {
        public static void main(String[] args) {
            Out skjerm = new Out();
            double omkrets;
    
            int radius = 1;
            while (radius <= 10) {
                omkrets = 2.0 * 3.14 * radius;
                skjerm.out("Radius = " + radius + " gir omkrets = ");
                skjerm.outln(omkrets, 2);
    	    radius++;
            }
        }
    }
    

    (b) Som forrige oppgave, men utskriften skal n? f?rst stoppe n?r omkretsen overstiger 1000.  Tips: Bruk while-l?kken til ? kontrollere O.
    import easyIO.*;
    class Omkrets3 {
        public static void main(String[] args) {
            Out skjerm = new Out();
            double omkrets = 0;
    
            int radius = 1;
            while (omkrets <= 1000) {
                omkrets = 2.0 * 3.14 * radius;
                skjerm.out("Radius = " + radius + " gir omkrets = ");
                skjerm.outln(omkrets, 2);
    	    radius++;
            }
        }
    }
    


  8. L?kker: Hva blir skrevet ut?
    Anta at f?lgende programsetninger utf?res. Hva skrives ut p? skjermen?


    class Ukeoppg2_8 {
        public static void main(String[] args) {
    
    //(a)
           int a = 1;
           while (a < 5) {
               a = a + 1;
           }
           System.out.println("a = " + a);
    
    
    a = 5
    
    
    //(b)
           int b = 11;
           while (b < 14) {
               b++;
               System.out.println(b);
           }
    
    
    12
    13
    14
    
    
    //(c)
           int c = 1;
           while (c < 10) {
               c = -2 * c;
           }
           System.out.println("c = " + c);
    
    
    c = 16
    
    
    //(d)
           for (int d = 0; d < 3; d++) {
               System.out.println(d);
           }
    
    
    0
    1
    2
    
    
    //(e)
           for (int e = 1; e <= 3; e++) {
               for (int f = 1; f <= 2; f++) {
                   System.out.println(e + " " + f);
               }
           }
    
    
    1 1
    1 2
    2 1
    2 2
    3 1
    3 2
    
    
    //(f)
           for (int ytre = 0; ytre < 2; ytre++) {
               System.out.print("[");
    
               for (int indre = 0; indre < 3; indre++) {  
                   System.out.print(".");
               }
               System.out.println("]");
           }
    [...]
    [...]
  9. En enkel array:
    int[] a = new int[20];
    
    (a) N?r setningen over utf?res, skjer det b?de en deklarasjon og en oppretting av et array-objekt. Forklar hvilken del av setningen som gj?r hva, og vis hvordan setningen kunne v?rt splittet opp i to setninger: en deklarasjonssetning og en setning som oppretter array-objektet.
    int[] a;
    a = new int[20];
    

    (b) Her er eksempler p? bruk av ovennevnte array.  Hva blir skrevet ut p? skjermen?
    int[] a = new int[20];
    a[0] = 100;
    a[1] = a[0] * 2;
    System.out.println(a[1]);
    a[0]++;
    System.out.println(a[0]);
    System.out.println(a.length);
    
    200
    101
    20
    

Oppgaver til terminaltimen

  1. Innlesing fra terminal: kap. 3, oppg. 3 (side 70)
    (Oppgaveteksten st?r i punkt 3. ovenfor)


  2. Utskrift med 2 desimaler p? to m?ter: easyIO og printf
    (Oppgaveteksten st?r i punkt 4. ovenfor)


  3. Valuta-omregning: kap. 3, oppg. 4 (side 70)
    Lag et program som leser inn et kronebel?p fra tastaturet, og omregner bel?pet til amerikanske dollar, euro, og svenske kroner; og skriver ut resultatet p? skjermen med to desimaler.  Omregningen er etter f?lgende kurser: 1 USD = 6.127 kr; 1 EUR = 7.865 kr; 1 SEK = 0.8436 kr.  (NB! Vekslingskursene er oppdatert 6. sep 2010, det st?r andre kurs og valutaer i l?reboka.)  [Valutakurser].  Hint: Hvis brukeren taster 100 skal resultatet i USD bli $16.32.
    import easyIO.*;
    
    class Valuta {
        public static void main (String[] args) {
    	In tast = new In();
    	Out skjerm = new Out();
    
    	// Valutakurser 29. aug 2008:
    	final double NOK_PR_USD = 6.127;
    	final double NOK_PR_EUR = 7.865;
    	final double NOK_PR_SEK = 0.8436;
    
    	// Leser input fra bruker:
    	System.out.print("Angi antall kr: "); // Ledetekst
    	double antallKr = tast.inDouble();
    
    	double antallUSD = antallKr / NOK_PR_USD;
    	double antallEUR = antallKr / NOK_PR_EUR;
    	double antallSEK = antallKr / NOK_PR_SEK;
    
    	// 2 desimaler vha. easyIO:
    	skjerm.out("Det tilsvarer i USD: $");
    	skjerm.outln(antallUSD, 2);
    
    	skjerm.out("  i britiske euro: EUR");
    	skjerm.outln(antallEUR, 2);
    
    	// 2 desimaler vha. printf:
    	System.out.printf("  i svenske kroner: SEK %.2f\n", antallSEK);
        }
    }
    
    KJ?REEKSEMPEL:
    > java Valuta
    Angi antall kr: 100
    Det tilsvarer i USD: $16.32
      i britiske pund: ?12.71
      i svenske kroner: SEK 118.54
    



  4. If-else med logisk uttrykk: kap. 4, oppg. 1 (side 82)
    Lag et program som avgj?r, basert p? alderen til en person, om personen kan f? reise med trikken til halv pris. Resultatet skal skrives ut p? skjermen. Vi antar at reglene er slik at alle under 12 ?r og alle over 64 ?r f?r reise for halv pris, mens alle andre m? betale full pris. Programmet skal lese personens alder fra terminal.

    Hint: Se eksemplet p? side 76, men legg til utskrift av en ledetekst (forklart i punkt 5. over).  I denne oppgaven trenger du ogs? logiske uttrykk (side 39).
    import easyIO.*;
    
    class Trikken {
        public static void main(String[] args) {
    	In tast = new In();
    
    	int alder;
    	int alderBarn = 12;
            int alderPensjonist = 64;
    
    	System.out.print("Oppgi alder: ");
    	alder = tast.inInt(); 
    
    	//  Logisk uttrykk som gir "true" hvis alder er mindre
    	//  enn "alderBarn" ELLER st?rre enn "alderPensjonist":
    	if (alder < alderBarn || alder > alderPensjonist) {
    	    System.out.println("Du kan betale halv pris.");
    	} else {
    	    System.out.println("Du m? betale full pris.");
    	}
        }
    }
    
    KJ?REEKSEMPEL:
    > java Trikken
    Oppgi alder: 25
    Du m? betale full pris.
    


  5. Summerings-l?kke: kap. 4, oppg. 6 (side 83)
    (a) Skriv et program som leser ett heltall n fra terminal, og som deretter summerer tallene fra 1 til n, dvs. 1 + 2 + ··· + n, og skriver ut hver av mellomresultatene (1; 1+2; 1+2+3; osv.), og sluttsummen.  Utskriften skal f?lge dette m?nsteret (n?r n = 5):
      1    1
      2    3
      3    6
      4   10
      5   15
    
    import easyIO.*;
    
    class Heltallssum {
        public static void main(String[] args) {
    	Out skjerm = new Out();
    	In tast = new In();
    
    	skjerm.out("Angi n: ");
    	int n = tast.inInt();
    
    	int sum = 0;
    	for (int i = 1; i <= n; i++) {
    	    sum = sum + i;
    	    skjerm.out(i, 3);
    	    skjerm.outln(sum, 5);
    	}
        }
    }
    
    KJ?REEKSEMPEL:
    > java Heltallssum
    Angi n: 5
      1    1
      2    3
      3    6
      4   10
      5   15
    
    (b) Det finnes ogs? en formel som gir summen av tallene 1, 2, 3, ...., n direkte: n * (n + 1) / 2.  Utvid programmet slik at det til slutt sammenligner siste sum med resultatet av formelen, og gir en melding til bruker p? om de to svarene var like eller ikke.
    	if (sum == n * (n + 1) / 2) {
    	    System.out.println("Formelen stemmer!");
    	} else {
    	    System.out.println("Formelen stemmer ikke.");
    	}
    



  6. L?kker: Hva blir skrevet ut?
    (Oppgaveteksten st?r i punkt 8. ovenfor)


  7. Gj?r ferdig Oblig 1.


  8. En enkel array:
    (Oppgaveteksten st?r i punkt 9. ovenfor). Mer om arrayer neste uke...


  9. Tilpasning av Emacs:
    NB! Emacs er ikke pensum, det er bare ett av mange mulige redigeringsprogrammer du kan bruke for ? skrive dine Java-programmer. Her kommer et nyttig lite tips for de som er interessert i Emacs, og link til mange flere tips.  Emacs kan konfigureres p? veldig mange m?ter slik at programmering blir mer behagelig. Dette gj?res ved ? opprette og redigere en spesiell fil i ditt hjemmeomr?de, kalt .emacs. Denne oppgaven viser én nyttig konfigurasjonsmulighet i Emacs, for ? fjerne velkomstskjermen som Emacs viser ved oppstart, slik at du slipper ? ta den vekk hver gang du skal starte arbeidet.

    Start Emacs for ? se velkomstskjermen, f.eks. ved ? taste kommandoen emacs& i et kommandovindu. Hvis Emacs-vinduet ikke viser noen "velkomstside" (hvor det st?r Emacs i store grafiske bokstaver, og diverse tekst i forskjellige farger) s? er tilpasningen allerede gjort p? ditt hjemmeomr?de og du trenger ikke gj?re noe mer. Hvis du derimot fikk opp velkomstsiden til Emacs, s? kan du fortsette med f?lgende steg og bruke denne samme Emacs-en du startet n? for ? ta bort velkomstskjermen, slik at den ikke forstyrrer neste gang du ?pner Emacs. Trykk Ctrl-x etterfulgt av Ctrl-f og s? taster du navnet p? konfigurasjonsfilen:
    Find file: ~/.emacs
    Sjekk at nederste linje i Emacs ser akkurat ut som dette, med tilde-tegn ("~"), skr?strek, og punktum rett etter "Find file: " og f?r emacs. Trykk Enter. Dette vil ?pne (og hvis n?dvendig opprette) konfigurasjonsfilen og flytte tekstmark?ren inn i den, slik at du kan redigere innholdet. Skriv (eller legg til) f?lgende linje i filen:
    (setq inhibit-splash-screen t)
    Deretter lagrer du filen ved ? trykke Ctrl-x Ctrl-s  Ferdig! N? kan du avslutte Emacs-en, og neste gang du starter programmet vil du ikke f? opp den gamle forstyrrende "velkomstsiden". 

    Du kan finne mange andre tips til Emacs i lab-oppgavene til Forkurs i informatikk, blant annet tips om klipping/liming (Ctrl-w og Ctrl-y), ?pning av flere 欧洲杯在线买球_欧洲杯投注网站推荐@ende Emacs-vinduer (Ctrl-x 52), automatisk korrigering av innrykk i et helt Java-program (Java > Indent Line or Region), og enkle tastetrykk som gir tekster som "public static void main(String[] args)" og "System.out.println()" (abbrevs).


Tibakemelding om dette oppgavesettet kan du skrive i bloggen eller sende p? mail til josek [a] ifi.uio.no