Twitter: @grzegg
Kategoria: java, Tagi: - - - .

Java [09] – Instrukcje wyboru cz. I

Programy, które dotychczas pisaliśmy miały charakter liniowy, to znaczy ich przebieg od początku do końca był zawsze taki sam. Zmieniały się co najwyżej wartości, które były przekazywane programowi i te, które wyliczał. Teraz poznamy konstrukcje, które pozwalają zmieniać przebieg programu i umożliwiać mu „podejmowanie” decyzji w zależności od sytuacji, na przykład od wartości zmiennych.

Ta strona jest częścią materiałów do kursu “Programowanie w Javie z elementami bioinformatyki dla poczatkujących”. Pozostałe materiały znajdziesz tutaj

Prawda czy fałsz?

Przy okazji omawiania rodzajów danych i zmiennych poznaliśmy typ boolean, który może przyjmować tylko jedną z dwu wartości: true (prawda) lub false (fałsz). Już wiemy jak można wyliczyć wartości liczbowe, ale jak można otrzymać wartości boolowskie? Jak komputer sprawdza, czy coś jest prawdą czy fałszem?

Najpierw zajmiemy się wartościami liczbowymi. Rozpatrzmy na przykład takie wyrażenie: 2<5. Można zadać pytanie, czy to wyrażenie jest prawdziwe, czy nie? Odpowiedź jest oczywista: „prawdziwe”. Spróbujmy zatem zadać takie pytanie komputerowi:


boolean wynik = 2<5;
System.out.println("Czy 2<5 to prawda, czy fałsz? Odpowiedź brzmi: "+wynik);

Po uruchomieniu, pojawi się taki wynik działania programu:


Czy 2<5 to prawda, czy fałsz? Odpowiedź brzmi: true

Jak widać, komputer dokonał porównania obu liczb, sprawdził, czy 2 jest mniejsza niż 3 i udzielił odpowiedzi. Sprawdź co się stanie, jeśli zmienisz znak <, na >. Rezultat jest łatwy do przewidzenia.
Oba znaki, których użyliśmy do porównania liczb są w tych wyrażeniach operatorami porównania, znanymi zresztą z lekcji matematyki.

A co jeśli trzeba będzie sprawdzić, czy dwie liczby są równe? Zapewne wpisałbyś taki kod:


boolean wynik = 2=5;

Niestety, to tak nie działa. Od razu NetBeans sygnalizuje błąd. Gdzie tkwi problem? Znak = jest znakiem przypisania i używamy go np. w takich sytuacjach jak przypisywanie wartości zmiennej. Natomiast nie służy do sprawdzania równości, w tym celu używamy dwóch znaków równości: ==. Czyli kod powinien wyglądać tak:


boolean wynik = 2==5;

Teraz, zgodnie z oczekiwaniami otrzymujemy wynik: false.
A co jeśli chcemy sprawdzić, czy jakaś wartość nie jest równa innej? Na takie okazje mamy zarezerwowany operator !=. Ponieważ prawdą jest, że 2 nie równa się 5, wyrażenie 2!=5 zwróci wynik: true.

Nie musimy osobno tworzyć zmiennej typu boolean i przypisywać jej wartości a następnie drukować wynik używając wartości zmiennej, całość można zmieścić w jednej linii. Pamiętać tylko należy, podobnie jak robiliśmy wcześniej przy okazji obliczeń, żeby wyrażenia umieszczać w nawiasach:


System.out.println(" Wynik porównania 2!=5 to: "+(2!=5));

Ze znanych z lekcji matematyki porównań pozostaje nam jeszcze „większy lub równy” i „mniejszy lub równy”. Operatory te również składają się z dwu znaków i wyglądają tak: >= oraz <=. Kolejność znaków ma znaczenie, wyrażenie => będzie nieprawidłowe. W poniższej tabelce znajduje się krótkie podsumowanie poznanych operatorów porównania.

Operatory porównania

operator przykład wynikiem jest prawda(true) jeśli:
== x == y x jest równe y
!= x != y x nie jest równe y
> x > y x jest większe niż y
< x < y x jest mniejsze niż y
>= x >= y x jest większe lub równe y
<= x <= y x jest mniejsze lub równe y

Wymienione operatory można też użyć w bardziej złożonych wyrażeniach. Na przykład sprawdźmy, czy liczba jest podzielna przez 2. Zastanów się jak sformułować takie wyrażenie.

To, że liczba jest podzielna przez 2 oznacza, że jeśli podzielimy ją przez 2 to nie otrzymamy reszty z dzielenia, czyli reszta będzie równa 0. Jak sprawdzić ile wynosi reszta z dzielenia? Pomoże tu kolejny operator dzielenia modulo: %. Wyrażenie x % y zwraca resztę z dzielenia x przez y. Można więc sprawdzić czy liczba jest podzielna przez 2 w ten sposób:


double reszta = 5%2;
System.out.println("Czy liczba 5 jest podzielna przez 2? "+ (reszta == 0));

Albo krócej:


System.out.println("Czy liczba 5 jest podzielna przez 2? "+ (5%2 == 0));

Jeżeli… – czyli instrukcje wyboru

Skoro już wiemy jak, przynajmniej w niektórych przypadkach, sprawdzić czy coś jest prawdą czy nie to przyszedł czas, żeby to wykorzystać. Jedną z możliwości zastosowania operatorów porównania jest ich wykorzystanie w instrukcjach warunkowych zwanych też instrukcjami wyboru lub instrukcjami sterującymi. Umożliwiają one uruchomienie (lub nie) komend lub dłuższych fragmentów kodu w zależności od tego czy określone warunki są spełnione czy nie. Pierwszą instrukcją tego typu jest if..else. W najprostszej postaci wygląda tak:


if (wyrażenie) {
//kod który się wykonuje, jeżeli wyrażenie zwraca wartość true
}

Umieszczone w nawiasie po if wyrażenie musi zwracać wartość true lub false. Może to być na przykład wyrażenie wykorzystujące operator porównania. Instrukcje zamknięte parą nawiasów {} tworzą blok instrukcji. Zauważ, że bloki tworzą także instrukcje obejmujące zawartość (ciało) klasy czy metody. Jeżeli blok kodu w instrukcjach takich jak if..else (ale nie w metodzie czy klasie) składa się z tylko jednej linii to parę nawiasów można ominąć.

Często nie tylko chcemy aby jakieś instrukcje wykonywały się, jeżeli wyrażenie jest prawdziwe, ale chcemy żeby jakiś inny blok instrukcji wykonywał się jeżeli wyrażenie zwraca wartość false. Wtedy możemy użyć wyrażenia if…else w takiej postaci:


if (wyrażenie) {
//kod który się wykonuje, jeżeli wyrażenie zwraca wartość true
}
else {
//kod który się wykonuje, jeżeli wyrażenie zwraca wartość false
}

Spróbujmy teraz wykorzystać świeżo zdobytą wiedzę do napisania prostego programu, który będzie sprawdzał czy podana przez użytkownika liczba jest liczbą parzystą. Przy okazji zapoznamy się ze schematami blokowymi.

Schematy blokowe

Schematy blokowe pozwalają przedstawić algorytm w sposób graficzny. Sposób działania naszego programu można zaprezentować na przykład tak:

Jak łatwo się domyśleć, strzałki symbolizują kierunek działania algorytmu (programu) a figury odpowiadają poszczególnym instrukcjom lub dłuższym fragmentom kodu.
Rodzaj użytych figur odpowiada charakterowi wykonywanych poleceń, których opis znajduje się wewnątrz.

Do najczęściej stosowanych figur należą:

kierunek działania programu

początek lub koniec programu

odczyt, zapis, wprowadzanie danych

decyzja, tu wpisuje się warunek

proces – różnego rodzaju instrukcje i bloki kodu inne niż powyższe

Zauważ, że od rombu symbolizującego decyzję wybiegają dwie strzałki, oznaczone TAK i NIE co odpowiada rezultatowi true lub false a każda z nich prowadzi do fragmentu kodu, który wykonuje się w zależności od rezultatu decyzji czyli od tego czy warunek jest prawdziwy czy nie.

Piszemy program z instrukcją if…else

Mając rozrysowany algorytm, łatwiej przystąpić do pisania kodu. Może on wyglądać tak:

Zagnieżdżanie

Instrukcje tego typu można zagnieżdżać. Na przykład przypuśćmy, że chcemy sprawdzić czy jeśli liczba jest nieparzysta to czy jest podzielna przez 3. W takim przypadku, w bloku kodu wykonywanym po else można umieścić kolejną instrukcję if…else:

Sposób działania programu można przedstawić na schemacie blokowym tak:

Przy okazji zwróć uwagę, że wewnętrzne bloki kodu są przesunięte w prawo (wcięte) względem bloków zewnętrznych co znacznie poprawia przejrzystość kodu. NetBeans IDE na ogół dba o prawidłowe wcięcia, ale nie zawsze to się udaje. Kod zwykle przesuwamy w prawo używając odpowiedniej liczby tabulatorów. Aby automatycznie poprawić źle sformatowany kod (nie tylko pod względem wcięć) można też użyć odpowiedniego polecenia z menu: Source->Format lub skrótu klawiszowego: Alt+Shift+F (Linux, Win), Ctrl+Shift+F(Mac). Jeśli zaznaczymy część kodu to powyższe polecenie będzie dotyczyć tylko zaznaczonego fragmentu. Oczywiście sposób formatowania przyjęty przez NetBeans nie zawsze musi nam odpowiadać.

Zadanie

Napisz program, który pobierze od użytkownika długości dwóch ramion chromosomów, obliczy stosunek ramion (krótsze ramię/dłuższe ramię) a następnie poda długość krótszego i dłuższego ramienia oraz obliczony stosunek długości ramion. Weź pod uwagę, że użytkownik może podać długość ramion w dowolnej kolejności a oba ramiona mogą mieć taką samą długość.

 

Ta strona jest częścią materiałów do kursu “Programowanie w Javie z elementami bioinformatyki dla poczatkujących”. Pozostałe materiały znajdziesz tutaj

4 komentarze Java [09] – Instrukcje wyboru cz. I

  • Mariusz

    Witam.
    Poniżej program.
    Proszę o odpowiedź, dlaczego przy int ramie1, ramie2 (nie double), a później przy operacji dzielenia (double)ramie2/ramie1 wynik to 0.0?
    Myślałem, że jak zmienne będą typu int, a przed wynikiem wstawię (double), to wynik będzie typu double i wyświetli się poprawnie.

    W chwili obecnej jeżeli ramiona są typu double wszystko działa ok.
    Z góry dziękuję za komentarz.

    import java.util.Scanner;

    /**
    * Created by ^^ on 2016-03-05.
    */
    public class Chromosomy {
    public static void main (String args[]) {
    Scanner podaj = new Scanner(System.in);

    System.out.println(„Podaj długość pierwszego ramienia”);
    double ramie1 = podaj.nextDouble();
    System.out.println(„Podaj długość drugiego ramienia”);
    double ramie2= podaj.nextDouble();

    if (ramie1 > ramie2) {
    System.out.println(„Długość krótszego ramienia to ” + ramie2);
    System.out.println(„Długość dłuższego ramienia to ” + ramie1);
    System.out.println(„Stosunek ramion wynosi ” +(ramie2/ ramie1)); //krotsze/dluzsze

    } else if (ramie2 > ramie1) {
    System.out.println(„Długość krótszego ramienia to ” + ramie1);
    System.out.println(„Długość dłuższego ramienia to ” + ramie2);
    System.out.println(„Stosunek ramion wynosi ” + (ramie1 / ramie2)); //krotsze/dluzsze
    } else if (ramie1 == ramie2) {
    System.out.println(„Oba ramiona mają taką samą długość, która wynosi ” + ramie1); //oba maja taka sama dlugos wiec nie ma roznicy, ktore ramie przypisze
    System.out.println(„Stosunek ramion wynosi 1”);

    }
    }
    }

    • Grzegorz

      Hmmm dziwne. Jak dokładnie ten fragment kodu z int-ami wyglądał?
      Jeśli uruchomię taki kod:


      int a = 2;
      int b = 4;
      double w = (double)a/b;
      System.out.println("w = " + w);

      To otrzymuję:
      w = 0.5

      Jeśli natomiast linijka z działaniem wygląda tak:


      double w = (double)(a/b);

      To dostajemy 0.0.

      Może więc działanie było w nawiasach?

  • Mariusz

    Dziękuję za pomoc.
    Faktycznie, ma Pan rację, po usunięcie nawiasów przy dzieleniu wszystko jest OK.

  • Croatoan

    /**
    * Created by Croatoan on 25.01.17.
    * IntelliJ IDEA 2016.3.3
    * System Linux Mint 18.1 Cinnamon
    *
    * Napisz program, który pobierze od użytkownika długości dwóch ramion chromosomów,
    * obliczy stosunek ramion (krótsze ramię/dłuższe ramię) a następnie poda długość
    * krótszego i dłuższego ramienia oraz obliczony stosunek długości ramion. Weź pod uwagę,
    * że użytkownik może podać długość ramion w dowolnej kolejności a oba ramiona mogą mieć taką samą długość.
    */

    import java.util.Scanner;

    public class RamionaChromosomow {
    public static void main (String args[]) {
    Scanner skanuj = new Scanner(System.in);

    System.out.println(„Podaj długość pierwszego ramienia chromosomu”);
    double ramiePierwszegoChromosomu = skanuj.nextDouble();
    System.out.println(„Podaj długość drugiego ramienia chromosomu”);
    double ramieDrugiegoChromosomu= skanuj.nextDouble();

    if (ramiePierwszegoChromosomu > ramieDrugiegoChromosomu) {
    System.out.println(„Długość krótszego ramienia chromosomu to ” + ramieDrugiegoChromosomu);
    System.out.println(„Długość dłuższego ramienia chromosomu to ” + ramiePierwszegoChromosomu);
    System.out.println(„Stosunek ramion chromosomów wynosi ” + (ramieDrugiegoChromosomu/ ramiePierwszegoChromosomu));

    } else if (ramieDrugiegoChromosomu > ramiePierwszegoChromosomu) {
    System.out.println(„Długość krótszego ramienia to ” + ramiePierwszegoChromosomu);
    System.out.println(„Długość dłuższego ramienia to ” + ramieDrugiegoChromosomu);
    System.out.println(„Stosunek ramion chromosomów wynosi ” + (ramiePierwszegoChromosomu / ramieDrugiegoChromosomu));

    } else if (ramiePierwszegoChromosomu == ramieDrugiegoChromosomu) {
    System.out.println(„Oba ramiona chromosomu mają taką samą długość, która wynosi ” + ramiePierwszegoChromosomu);
    System.out.println(„Stosunek ramion wynosi 1”);

    }
    }
    }

Leave a Reply