Računalništvo 1 (PRA)

lekcije / Spremenljivke in aritmetične operacije

Spremenljivke in aritmetične operacije

Aritmetične operacije in elementarne funkcije

Računalnike imamo zato, da z njimi kaj računamo. Na primer:
Produkt.java
1
2
3
4
5
public class Produkt {
    public static void main(String[] args) {
	int x = 1234 * 4321;
    }
}
Ta program izračuna produkt števil 1234 in 4321. Ko ga prevedemo in poženemo, seveda ne vidimo, kolikšen je produkt, ker program rezultata ne izpiše ne zaslon, ampak ga shrani v spremenljivko x:
> javac Produkt.java
> java Produkt
>
Če bi želeli videti rezultat, bi dodali ukaz za izpis na ekran:
Produkt2.java
1
2
3
4
5
6
public class Produkt2 {
    public static void main(String[] args) {
	int x = 1234 * 4321;
	System.out.println(x);
    }
}
> javac Produkt2.java
> java Produkt2
5332114
>
Program bi lahko napisali tudi takole:
Produkt3.java
1
2
3
4
5
public class Produkt3 {
    public static void main(String[] args) {
	System.out.println(1234 * 4321);
    }
}
> javac Produkt3.java
> java Produkt3
5332114
>
Kot vidimo, Produkt3 izpiše isto kot Produkt2, vendar med njima obstaja bistvena razlika. Program Produkt2shrani rezultat v spremenljivkox, medtem ko ga Produkt3 samo izpiše na ekran. To je pomembno, kadar rezultat potrebujemo v nadalnjem računanju.
Računske rezultate, ki jih še potrebujemo v nadalnjem računanju, moramo spraviti v spremenljivko.
V Javi (pa tudi v večini programskih jezikov) je množenje označeno z zvezdico *. Kakšne osnovne aritmetične operacije še pozna Java? Naštete so v spodnji tabeli:
Aritmetične operacije
x + yvsota
s + t stakni niza String s in String t
x - y razlika
x * y zmnožek
x / y kvocient
x % y ostanek pri delenju
-x obratna vrednost
x >> k bitni pomik v desno za k mest (deli x z 2^k)
x << k bitni pomik v levo za k mest (množi x z 2^k)
x & y bitni 'in'
x | y bitni 'ali'
x ^ y bitni 'ekskluzivni ali'
~x bitni komplement
p ? x : y če velja p, potem je vrednost x, sicer y
Primerjave in logične operacije
x == y x je enak y (x in y sta osnovnega tipa)
x.equals(y) x je enak y (x in y sta objekta)
x != y x ni enak y (x in y sta osnovnega tipa)
x < y x je manjši od y
x > y x je večji od y
x <= y x je manjši ali enak y
x >= y x je večji ali enak y
p && q logični 'in'
p || q logični 'ali'
! p logični 'ne'
Okrajšave
krajšedaljše
i++ i = i + 1
i-- i = i - 1
x += y x = x + y
x -= y x = x - y
x *= y x = x * y
x /= y x = x / y
Danes bomo preizkusili le seštevanje, odštevanje, množenje, delenje in ostanke. Preizkusimo jih s preprostim programom:
Operacije.java
1
2
3
4
5
6
7
8
9
public class Operacije {
    public static void main(String[] args) {
	System.out.println(12 * 5);
	System.out.println(12 + 5);
	System.out.println(12 - 5);
	System.out.println(12 / 5);
	System.out.println(12 % 5);
    }
}
> javac Operacije.java
> java Operacije
60
17
7
2
2
>
Torej, 12 krat 5 je 60, 12 plus 5 je 17, 12 minus 5 je 7. Kaj pa 12 deljeno s 5? Ali je res 2? Ne, ampak 2.4. Računalnik se je zmotil! Pravzaprav se ni zmotil, ampak je uporabil celoštevilsko delenje, ker smo delili cela števila 12 in 5. Torej: 12 deljeno s 5 je 2 (in ostane 2). Zadnja operacija, označena z znakom "%" je ostanek pri delenju.
Kako pa dopovemo Javi, da želimo operacije z realnimi števili in ne s celimi? Tako, da zapišemo števila z decimalno piko:
RealnoDelenje.java
1
2
3
4
5
public class RealnoDelenje {
    public static void main(String[] args) {
	System.out.println(12.0 / 5.0);
    }
}
> javac RealnoDelenje.java
> java RealnoDelenje
2.4
>
Pa smo dobili pričakovani rezultat. Torej, 12 je za Javo celo število, 12.0 pa realno. Pravzaprav Java ne pozna pravih realnih števil, ampak števila z omejeno natančnostjo, ki se v Javi imenujejo "double" (od "double floating point number"). Za večino izračunov natančnost, ki jo ponujajo števila double zadošča. Mi jim bomo rekli kar "realna števila", čeprav to zares niso.
Tudi cela števila so omejena. Največje in najmanjše celo število, s katerimi Java še zna računati sta Integer.MAX_VALUE in Integer.MIN_VALUE.
NajvecjaStevila.java
1
2
3
4
5
6
public class NajvecjaStevila {
    public static void main(String[] args) {
	System.out.println(Integer.MAX_VALUE);
	System.out.println(Integer.MIN_VALUE);
    }
}
> javac NajvecjaStevila.java
> java NajvecjaStevila
2147483647
-2147483648
>
Če prekoračimo te meje, dobimo zelo čudne rezultate, na primer:
KvadratStevila.java
1
2
3
4
5
6
public class KvadratStevila {
    public static void main(String[] args) {
	int x = 1000000 * 1000000;
	System.out.println(x);
    }
}
> javac KvadratStevila.java
> java KvadratStevila
-727379968
>
To je seveda nesmiselen rezultat, saj je kvadrat celega števila pozitiven, mi pa smo dobili negativno število. V zvezi z računanjem s števili si torej zapomnimo:
Java pozna cela števila, tip int, in realna števila, tip double. Oboja so po velikosti omejena, realna števila pa imajo tudi omejeno natančnost. V večini primerov nam glede tega ni treba skrbeti.
Realna števila pišemo z decimalno piko, na primer 12.0, cela števila pa brez decimalne pike, na primer 12.
Naloga 1
[rešitev]
Kako pa izračunamo elementarne funkcije, kot so logaritem, eksponentna fukncija, sinus, kosinus, ipd.? Vse te funkcije so priskrbljene v standardni knjižnici, v razredu Math.
Naloga 2
Namig
Mogoče se vam zdi, da ta vaja ni mišljena resno. Pa je, vsaj 70% mišljena zelo resno. Kot programerji se morate namreč navaditi brskati po dokumentaciji.
[rešitev]
Na primer, kako izračunamo kosinus 60 stopinj? (Vsi vemo da je odgovor 0.5, zanima nas, kako se to naredi v Javi.) Preden napišemo program, se spomnimo, da je treba pisati realna števila z decimalno piko--torej bomo zapisali šestdeset kot 60.0 in ne kot 60.
Kosinus.java
1
2
3
4
5
6
public class Kosinus {
    public static void main(String[] args) {
	double x = Math.cos(60.0);
	System.out.println(x);
    }
}
> javac Kosinus.java
> java Kosinus
-0.9524129804151563
>
Hm, rezultat bi moral biti 0.5. Kaj je narobe? Zelo težko boste odkrili, če ne boste prebrali dokumentacije za Math.cos. Tam lepo piše, da mora biti kot podan v radianih in ne v stopinjah! V dokumentaciji tudi piše, da obstaja metoda Math.toRadians, ki pretvarja iz stopinj v radiane. Oboroženi z novim znanjem poskusimo še enkrat:
Kosinus2.java
1
2
3
4
5
6
public class Kosinus2 {
    public static void main(String[] args) {
	double x = Math.cos(Math.toRadians(60.0));
	System.out.println(x);
    }
}
> javac Kosinus2.java
> java Kosinus2
0.5000000000000001
>
To je pa že bolje, čeprav ni čisto prav. Do napakice je prišlo, ker imajo števila tipa double omejeno natančnost.
Naloga 3
[rešitev]

Spremenljivke

V drugem delu te lekcije bomo povedali še nekaj podrobnosti o spremenljivkah ali variablah (angl. "variable"). Kot že vemo, v programskem jeziku uporabljamo spremenljivke namesto pomnilniških lokacij, prevajalnik pa uporabo spremenljivk predela v uporabo pomnilniških lokacij. S tem je programiranje bolj pregledno in lažje.
Prevajalnik mora vedeti, koliko pomnilnika naj rezervira za vsako spremenljivko. Zato je treba prvič, ko spremenljivko omenimo, povedati kakšnega tipa je. Pravimo, da smo spremenljivko deklarirali:
  1. V programskem jeziku uporabljamo spremenljivke namesto pomnilniških lokacij.
  2. Prvič, ko spremenljivko omenimo, jo moramo deklarirati, kar pomeni, da povemo njen tip in začetno vrednost:
    int st = 7;
    double temperatura = 14.0;
    Zaenkrat poznamo le dva tipa, int za cela števila in double za realna števila.
  3. Ime spremenljivke se mora začeti s črko in je lahko sestavljeno iz črk, številk in podčrtaja.
Ukazi v Javi so razdeljeni na bloke. Blok se začne z zavitim oklepajem { in konča s pripadajočim zavitim zaklepajem }. Na primer:
1
2
3
4
5
6
7
8
9
10
11
12
{
  int x = 7;
  int y = 8;

  if (x > y) {
     int t = x;
     x = y;
     y = t;
  }

  int t = (3 * x) % y;
}
Ta program je sestavljen iz enega velikega bloka (vrstice 1--12), v njem pa je vgnezden še en blok (vrstice 6--8).
Spremenljivke v Javi so lokalne. To pomeni, da spremenljivka obstaja le od deklaracije do zaključka bloka, v katerem je deklaracija vsebovana. V zgornjem programu je veljavnost spremenljivk naslednja: Zunaj območja veljavnosti spremenljivke preprosto ni! Ko prevajalnik prevede program, rezervira lokacijo v pomnilniku za vsako spremenljivko, vendar samo začasno. Preden spremenljivka postane veljavna in ko ni več veljavna, lahko prevajalnik porabi isto lokacijo za kako drugo spremenljivko.
Iz zgornjega programa se naučimo še nekaj: v vrsticah 6--8 je veljavna spremenljivka t, v vrsticah 11--12 pa druga spremenljivka, ki se tudi imenuje t. To je seveda mogoče, ker se območji veljavnosti za ti dve spremenljivki ne prekrivata. Zapomnimo si, da sta to povsem različni spremenljivki.
Zapomnimo si:
  1. Spremenljivke v Javi so lokalne.
  2. Spremenljivka je veljavna od deklaracije do konca bloka, v katerem je deklarirana.
  3. Različne spremenljivke imajo lahko isto ime, če se njihova območja veljavnosti ne prekrivajo.
Naloga 4
[rešitev]
Naloga 5
Naloga 6
Namig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Denar {
  public static void main(String[] args) {
    int k = tu vstavi zacetno vrednost;
    int k10, k5, k2, k1;

    tu napisi svoj program

    System.out.print(k + " tolarjev = ");
    System.out.print(k10 + " kovancev za 10 + ");
    System.out.print(k5 + " kovancev za 5 + ");
    System.out.print(k2 + " kovancev za 2 + ");
    System.out.println(k1 + " kovancev za 1 tolar.");
  }
}

Rešitve nalog

Naloga 1

Največje realno število je Double.MAX_VALUE. Tukaj je dokumentacija.
Napišimo še program, ki to število izpiše. Ko brskamo po dokumentaciji (dobri programerji vedno brskajo po dokumentaciji in jo berejo za zabavo pred spanjem), opazimo še, da je Double.MIN_VALUE najmanjše veljavno pozitivno realno število. S programom izpišemo obe:
NajvecjiDouble.java
1
2
3
4
5
6
7
8
9
public class NajvecjiDouble {
    public static void main(String[] args) {
	System.out.print("Najvecje realno stevilo je ");
	System.out.println(Double.MAX_VALUE);

	System.out.print("Najmanjse pozitivno realno stevilo je ");
	System.out.println(Double.MIN_VALUE);
    }
}
> javac NajvecjiDouble.java
> java NajvecjiDouble
Najvecje realno stevilo je 1.7976931348623157E308
Najmanjse pozitivno realno stevilo je 4.9E-324
>
To je pa zelo čuden izpis, ali ne? Črka 'E' pomeni "krat deset na", torej preberemo takole: "1.7976931348623157E308 je enako 1.7976931348623157 krat deset na 308" in "4.9E-324 = 4.9 krat deset na -324".

Naloga 2

Dokumenatcija o razredu Math je tukaj.

Naloga 3

Senca.java
1
2
3
4
5
6
7
public class Senca {
    public static void main(String[] args) {
	System.out.print("Dolzina predavateljeve sence je ");
	System.out.print(183.0 / Math.tan(Math.toRadians(42.0)));
	System.out.println(" cm.");
    }
}
> javac Senca.java
> java Senca
Dolzina predavateljeve sence je 203.2420902137423 cm.

Naloga 4

Arjana je program popravila takole:
Arjana.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Arjana {
    public static void main(String[] args) {
	int x = 7;
	int y = 8;
	int z;

	if (x < y) {
	    z = x;
	}
	else {
	    z = y;
	}

	System.out.println(z);
    }
}
Andrej pa se je šopiril z znanjem Jave in je napisal tale program:
Andrej.java
1
2
3
4
5
6
7
8
public class Andrej {
    public static void main(String[] args) {
	int x = 7;
	int y = 8;
	int z = (x < y) ? x : y;
	System.out.println(z);
    }
}
Oba delujeta pravilno.