L?sningsforslag ukeoppg. 3:  7. - 13. sep (INF1000 - H?st 2011)

Utskrift/ lesing med easyIO, arrayer, l?kker   (kapittel 3-4 i l?reboka, "Rett p? Java" 3. utg.)

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 uttrykk, innlesing og utskrift til terminal, l?kker, og arrayer.

[N?kkeloppg.]: Oppgave merket med n?kkelsymbol er plukket ut som spesielt representativ for de viktigste temaene fra ukens forelesning, og alle b?r ha som minimumsm?l ? l?se denne selvstendig.

Oppgaver

  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 39 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 41)
    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 72)
    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: 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, til dette kan du bruke enten EasyIO eller Javas innebygde funksjoner:
    • EasyIO: F?lg malen fra eksemplet p? side 58.  Bruk tast.inDouble() og ikke tast.inInt() slik at bruker kan taste inn et flyttall. 

    • Scanner: NB! Dette er bare ment for spesielt interesserte som vil pr?ve uten EasyIO.
      Se denne tabellen i bloggen med programsetninger i Java 1.5 som tilsvarer EasyIO.

    I begge tilfeller s? vil programsetningen som leser inn tallet (tast.inInt() eller scan.nextInt()) stoppe kj?ringen av programmet midlertidig 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 med EasyIO:
    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.


    L?sningsforslag med Scanner:
    Kommer...


  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:

    • EasyIO: Hvis pakken EasyIO er installert p? maskinen du bruker s? kan man f? skrevet ut variabelen tall med 2 desimaler etter komma, og evt. p? akkurat 7 plasser ved hjelp av f?lgende setninger. I det andre eksemplet s? fyller Java p? med blanke tegn til venstre slik at hele utskriften tar 7 plasser (eller s? mange plasser som er n?dvendig):
        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 52 i l?reboka.  I tillegg m? easyIO v?re installert p? datamaskinen (mer om dette kan du lese i bloggen). For info om andre muligheter for formatert utskrift med easyIO se oversikten p? side 54.  Ledeteksten "Tall: " kan skrives ut vha. en egen skjerm.out("Tall: ")-setning som du kan plassere f?r de ovennevnte skjerm.outln-setningene.

    • Printf: NB! Dette er bare ment for spesielt interesserte som vil pr?ve uten EasyIO.
      I de vanligste brukte versjoner av Java (5.0, 6, og 7, ogs? kalt 1.5, 1.6, og 1.7) finnes en metode kalt "printf" som gir oss god kontroll over utskriften, f?lgende setninger gir samme resultat som EasyIO-setningene ovenfor:
        System.out.printf("Tall: %.2f\n", tall);
        System.out.printf("Tall: %7.2f\n", tall);
      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.

    Oppgave: Bruk dette til ? endre programmet fra forrige oppgave (oppgave 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. Valuta-omregning: kap. 3, oppg. 4 (side 73)
    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 = 5.435 kr; 1 EUR = 7.682 kr; 1 SEK = 0.8462 kr.  (NB! Vekslingskursene er oppdatert 6. sep 2011, det st?r andre kurs og valutaer i l?reboka.)  [Valutakurser].  Hint: Hvis brukeren taster 100 skal resultatet i USD bli $18.40.
    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 = 5.435;
            final double NOK_PR_EUR = 7.682;
            final double NOK_PR_SEK = 0.8462;
    
            // 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 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: $18.40
      i euro: EUR13.02
      i svenske kroner: SEK 118.18
    


  6. For-l?kke: kap. 4, oppg. 4 (side 85)
    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. [N?kkeloppg.]: While-l?kke: (b): kap. 4, oppg. 5 (side 85)
    (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. Summerings-l?kke: kap. 4, oppg. 6 (side 85)
    (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.");
    	}
    


  9. 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("]");
           }
    [...]
    [...]



  10. 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
    


  11. Array med tall:
    (a) Lag et program som ber bruker taste inn tre heltall og lagrer disse i en array kalt tall:
    int[] tall = new int[3];
    
    (b) Sum av array: Utvid programmet slik at det regner ut summen av tallene ved hjelp av en l?kke, og skriver ut resultatet.
    (c) Minste verdi: Utvid programmet slik at det finner og skriver ut det minste tallet i arrayen.
    (d) Lave verdier: Legg til programkode som skriver ut alle verdiene i arrayen som er mindre enn 10.
    (e) S?k: Legg til programkode som skriver ut en beskjed om verdien 5 finnes eller ikke finnes i arrayen.
    import easyIO.*;
    class Ukeoppg3_3 {
        public static void main(String[] args) {
            In tast = new In();
            Out skjerm = new Out();
    
            int[] tall = new int[3];
    
            // (a) Lese 3 tall fra tastatur:
            for (int i = 0; i < 3; i++) {
                // Ledetekst:
                skjerm.out("Angi tall[" + i + "]: ");
    
                // Les et tall fra tastatur og lagre det i arrayen tall[]:
                tall[i] = tast.inInt();
            }
    
            // (b) Sum av array:
            int sum = 0;
            for (int i = 0; i < 3; i++) {
                sum += tall[i];
            }
            skjerm.outln("(b) Sum av tallene = " + sum);
    
            // (c) Minste verdi:
            int minste = tall[0];
            for (int i = 0; i < 3; i++) {
                if (tall[i] < minste) {
                    minste = tall[i];
                }
            }
            skjerm.outln("(c) Minste verdi = " + minste);
    
            // (d) Lave verdier:
            skjerm.out("(d) Lave verdier (< 10): ");
            for (int i = 0; i < 3; i++) {
                if (tall[i] < 10) {
                    skjerm.out(tall[i] + " ");
                }
            }
            skjerm.outln();
    
            // (e) S?k:
            boolean funnet = false;
            for (int i = 0; i < 3; i++) {
                if (tall[i] == 5) {
                    funnet = true;
                }
            }
            skjerm.out("(e) Verdien 5 finnes ");
            if (! funnet) {
                skjerm.out("ikke ");
            }
            skjerm.outln("i arrayen");
        }
    }
    
    KJ?REEKSEMPEL:
    > java Ukeoppg3_3
    Angi tall[0]: 2
    Angi tall[1]: 7
    Angi tall[2]: 11
    (b) Sum av tallene = 20
    (c) Minste verdi = 2
    (d) Lave verdier (< 10): 2 7 
    (e) Verdien 5 finnes ikke i arrayen


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