162 78 21MB
Polish Pages [433] Year 2012
Od autora Niniejszy zbiór zada jest propozycj dla rozpoczynajcych nauk programowania w jzyku Java. Jak sugeruje tytu (moe nieco dziwnie zbudowany), Czytelnik znajdzie tutaj zadania z zakresu programowania i podpowiedzi (wskazówki) dotyczce tego, jak zabra si do ich rozwizywania. Jeli informacja zawarta w treci zadania i ewentualna podpowied (wskazówka, uwaga) oka si niewystarczajce, to mona sign do odpowiedzi, gdzie zawarto dodatkowe wskazówki, istotne fragmenty rozwizania lub kompletne listingi kodów ródowych. Kady dzia jest poprzedzony krótkim wprowadzeniem teoretycznym, przykadem lub linkiem do odpowiedniego fragmentu dokumentacji jzyka zamieszczonej w internecie. W pocztkowych rozdziaach umieszczono w tekcie zada sugerowane nazwy plików ródowych (np. w zadaniu 2.3 zaproponowano nazw pliku Adres.java). Rozwizujc zadanie, Czytelnik powinien pamita, e nazwa klasy musi by identyczna z nazw pliku (bez rozszerzenia). Sugerowanie nazw plików (a przy tym nazw klas) ma na celu przyzwyczajenie Czytelnika do dobierania nazw klas odpowiednich do treci zadania. Ponadto róne nazwy plików (klas) umoliwiaj gromadzenie rozwiza kilku zada w tym samym folderze. W dalszej czci zbioru zaproponowano nazwy plików zgodne z numerami zada, np. rozwizanie zadania 13.8 zapisano w pliku Z13 8.java, a inny wariant rozwizania tego zadania zapisano w pliku Z13 8a.java. Aby uatwi Czytelnikowi poszukiwanie plików z rozwizaniami, rozwizanie na przykad zadania 2.3 (i innych pocztkowych zada) zawarto dodatkowo w pliku Z02 3.java. Wszystkie pliki ródowe umieszczono na serwerze ftp://ftp.helion.pl/przyklady/projaz.zip).
6
Programowanie w jzyku Java
Rozdzia 1.
Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java 1. Historia Javy i pierwsze zadania Zespó inynierów z firmy Sun, pracujc pod kierownictwem Jamesa Goslinga, rozpocz w 1991 roku projekt pod nazw Green. Celem projektu byo utworzenie jzyka programowania dla niewielkich urzdze elektronicznych. Jzyk mia by niezaleny od platformy sprztowej. Doprowadzio to do utworzenia kodu poredniego dla maszyny wirtualnej, który mona uruchamia w kadym urzdzeniu wyposaonym w odpowiedni interpreter. Przez kilka lat projekt rozwija si, ale produkt nie uzyskiwa podanej popularnoci. Jzyk pocztkowo nazwano Oak (db), ale gdy okazao si, e ta nazwa jest ju zajta, zmieniono j na Java. Przeomem w rozwoju tego jzyka stao si napisanie w nim przegldarki internetowej HotJava. Umoliwiaa ona uruchamianie kodu wbudowanego w strony internetowe, czyli tzw. apletów. Efekty pracy opublikowano w maju 1995 roku w magazynie „Sun Word” i odtd Java zacza zyskiwa popularno. Na pocztku 1996 roku ukazaa si pierwsza oficjalna wersja jzyka — Java 1.0. Hasem promujcym Jav byo zdanie Write Once, Run Anywhere („Napisz raz, uruchamiaj wszdzie”). W kolejnych wersjach uzupeniano zauwaone braki i dodawano nowe funkcjonalnoci. Systematycznie rosa liczba klas i interfejsów:
14
Programowanie w jzyku Java
lub: for(int i = tablica.length 1; i >= 0;
i) instrukcja; /* Odliczanie w dó */
Zadanie 3.5. Utwórz tablic zawierajc znaki sowa programowanie. Napisz program odwracajcy kolejno znaków w tablicy (plik ródowy: Wspak2.java). Przestawiaj kolejno pary elementów tablicy: pierwszy z ostatnim, drugi z przedostatnim — a dojdziesz do rodka tablicy.
Zadanie 3.6. Przeanalizuj kod podany na listingu 2. Przepisz kod i uruchom t aplikacj. Sprawd , czy wyniki na ekranie s zgodne z Twoimi oczekiwaniami. Na podstawie tego kodu i dokumentacji klasy Character napisz wasn aplikacj pokazujc dziaanie wybranej metody lub wartoci zdefiniowanych staych. Listing 2. DemoCharacter.java import static java.lang.System.*; public class DemoCharacter { public static void main(String args[]) { /* Informacje o metodzie */ out.println("Klasa: java.lang.Character"); out.println("Metoda statyczna: digit\n"); out.println("static int digit(int ch, int radix)"); out.println("Returns the numeric value of the character ch in the specified radix."); out.println(); /* Przykadowa tablica znaków */ char znak[] = {'E', 'u', 'r', 'o', ' ', '2', '0', '1', '2'}; /* Demonstracja dziaania metody */ out.println("Warto znaku jako cyfry w ukadzie dziesitkowym (radix = 10)"); for(char z : znak) out.println("Znak: "+z+" Cyfra: "+Character.digit(z, 10)); out.println("Uwaga: 1 oznacza, e znak nie jest cyfr w tym ukadzie liczbowym."); out.println(); out.println("Warto znaku jako cyfry w ukadzie szesnastkowym (radix = 16)"); for(char z : znak) out.println("Znak: "+z+" Cyfra: "+Character.digit(z, 16)); out.println("Uwaga: 1 oznacza, e znak nie jest cyfr w tym ukadzie liczbowym."); } }
Rozdzia 1. i Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java
15
Zadanie 3.7. Napisz program, który utworzy dziesicioelementow tablic znaków i wypeni j cyframi od 0 do 9 (plik ródowy: Cyfry.java). Zadeklaruj tablic znaków o odpowiednim wymiarze. Wykorzystaj tabel kodów ASCII i moliwo zamiany kodu znaku na odpowiadajcy mu znak np. przez rzutowanie: (char)65 zamienia liczb 65 na znak o kodzie 65, czyli wielk liter 'A'.
Zadanie 3.8. Napisz program, który utworzy szesnastoelementow tablic znaków i wypeni j cyframi ukadu szesnastkowego (plik ródowy: Cyfry16.java). Moesz postpi podobnie jak w zadaniu 3.7 lub wykorzysta statyczn metod forDigit() z klasy Character.
4. Klasa String — operacje na tekstach W Javie nie ma wbudowanego typu prostego do przechowywania cigów (acuchów) znaków. Kady acuch znaków jest obiektem klasy String nalecej do standardowej biblioteki. Klasa String oferuje kilka konstruktorów i szereg metod (ponad 50) do przetwarzania acuchów. Literay acuchowe zapisujemy w cudzysowie, np. "Zadania z programowania". Ten litera jest obiektem i na jego przykadzie zostanie pokazanych kilka metod klasy String.
Zadanie 4.1. Uruchom aplikacj, której kod ródowy przedstawiono na listingu 3. Na podstawie obserwacji wyników dziaania programu opisz dziaanie uytych metod klasy String. W przypadku wtpliwoci zajrzyj do dokumentacji jzyka Java (np. http://download. oracle.com/javase/6/docs/api/java/lang/String.html). Listing 3. TestString.java public class TestString { public static void main(String args[]) { System.out.println("Zadania z programowania."); System.out.println("Zadania z programowania.".charAt(0)); System.out.println("Zadania z programowania.".length()); System.out.println("Zadania z programowania.".charAt(23)); System.out.println("Zadania z programowania.".toUpperCase()); System.out.println("Zadania z programowania.".toLowerCase()); System.out.println("Zadania z programowania.".indexOf('z')); System.out.println("Zadania z programowania.".indexOf("prog")); System.out.println("Zadania z programowania.".replace('.', '?'));
16
Programowanie w jzyku Java System.out.println("Zadania z programowania.". replace("adania", "dania")); System.out.println("Zadania z programowania.". replaceAll("ania", "anka")); System.out.println("Zadania z programowania.". replaceFirst("ania", "anka")); System.out.println("Zadania z programowania.".substring(10)); System.out.println("Zadania z programowania.".substring(10, 17)); System.out.println("Zadania z programowania.". concat("\b z podpowiedziami.")); System.out.println("Zadania z programowania."+"\b"+ " z odpowiedziami."); } }
Oczywicie moemy tworzy zmienne typu obiektowego String. Poniewa raz utworzony acuch znaków (ang. string) nie moe by zmieniany, to kada operacja powoduje tworzenie nowego acucha. Zmienna jest referencj do acucha znaków, wic moemy przypisa jej inny acuch (w szczególnoci zmieniony obraz acucha, który wskazywaa wczeniej). Nie powoduje to problemów z pamici, gdy zbdne obiekty w Javie s automatycznie usuwane. Utworzon zmienn naley zainicjowa: String napis = "Zadania z programowania.";
lub: String napis = new String("Zadania z programowania.");
acuch moemy równie utworzy z tablicy znaków, np.: char[] znaki = {'z', 'a', 'd', 'a', 'n', 'i', 'e'}; String napis = new String(znaki);
Zadanie 4.2. Napisz program z listingu 3., wykorzystujc zamiast literaów zmienne reprezentujce obiekty typu String lub zmienne typu char. Klas nazwij DemoString. Aby kod by czytelny, wprowad odpowiednie nazwy zmiennych, np. char kropka = '.'; itp.
Rozwiemy teraz kilka zada podobnych do zada z rozdziau 3. Zastpimy tablic znaków odpowiednim acuchem. Naley jednak pamita, e pomimo jednakowej zawartoci te obiekty si róni. Moemy dokonywa konwersji w obie strony pomidzy tablic i acuchem znaków.
Zadanie 4.3. Utwórz acuch zawierajcy napis Dzie dobry. Napisz aplikacj (plik ródowy: WitajStr. java), która wywietli napis w konsoli: a) pionowo — kady znak w odrbnym wierszu,
Rozdzia 1. i Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java
17
b) poziomo — znaki rozdzielone dodatkowymi odstpami (tzw. spacjowanie
lub rozstrzelenie tekstu), c) poziomo — wielkimi literami, d) poziomo — maymi literami. W podpunktach a) i b) moesz skorzysta z ptli typu for i metody charAt(). Mona te dokona konwersji acucha na tablic znaków (metoda toCharArray() z klasy String) i dalej postpowa wedug rozwizania zadania 3.2.
Zadanie 4.4. Utwórz acuch znaków zawierajcy sowo programowanie. Napisz program zmieniajcy zawarto acucha i wywietlajcy efekty tych zmian (plik ródowy: ProgramowanieStr.java): a) zamie pierwsz liter na wielk, b) zamie wszystkie litery na wielkie. Moemy utworzy nowy acuch, speniajcy warunki zadania, i przypisa jego warto tej samej zmiennej. Dotychczasowa warto zostanie usunita z pamici w chwili, gdy nie bdzie ju dalej potrzebna.
Zadanie 4.5. Utwórz acuch znaków zawierajcy sowo programowanie. Napisz program, który znaki zawarte w acuchu bdzie wywietla w kolejnoci odwrotnej, od koca do pocztku (plik ródowy: WspakStr1.java).
Zadanie 4.6. Utwórz acuch znaków zawierajcy sowo programowanie. Napisz program odwracajcy kolejno znaków w acuchu (plik ródowy: WspakStr2.java). Zob. wskazówk do zadania 4.4.
Zadanie 4.7. Napisz program, który utworzy acuch znaków wypeniony cyframi od 0 do 9 (plik ródowy: CyfryStr.java). Rozwizanie tego zadania jest zupenie banalne — poprawna odpowied to: String cyfry = "0123456789";. Spróbuj jednak zbudowa ten acuch z poszczególnych znaków (zob. zadanie 3.7). Takie podejcie do zagadnienia moe w przyszoci si przyda .
18
Programowanie w jzyku Java
Zadanie 4.8. Napisz program, który utworzy acuch znaków wypeniony cyframi ukadu szesnastkowego (plik ródowy: CyfryStr16.java). Zob. wskazówk do zadania 4.7.
5. Tablica argumentów aplikacji W nagówku metody main()jest zadeklarowana tablica argumentów String args[] lub String[] args. W tablicy zawarte s referencje do obiektów typu String przekazanych przez system operacyjny podczas uruchomienia aplikacji poleceniem: java NazwaKlasy parametr1 parametr2 ... parametrN
Pole args.length zawiera liczb przekazanych argumentów. Argumenty w programie s dostpne przy uyciu indeksów od 0 do args.length–1: args[0], args[1], …, args[N–1], gdzie N oznacza liczb argumentów. Jeli aplikacj wywoamy bez dodatkowych parametrów (java NazwaKlasy), czyli liczba argumentów bdzie równa 0, to wtedy tablica args bdzie pusta (nie bdzie zawiera adnego elementu). W kolejnych zadaniach wykorzystamy tablic argumentów do przekazywania danych do aplikacji.
Zadanie 5.1. Napisz program, który wywietli na ekranie liczb argumentów wywoania aplikacji oraz podane argumenty. Kady argument powinien by wywietlony w odrbnym wierszu (plik ródowy: Argumenty.java). Do przegldania zawartoci tablicy wykorzystaj ptle typu for lub for each (zob. zadanie 3.2).
Zadanie 5.2. Napisz program (plik ródowy: Osoba.java), który uruchamiany z dwoma parametrami, imi i nazwisko, wywietli na ekranie w kolejnych wierszach te dane wedug schematu: Nazwisko: Kowalska Imi: Maria Nazwisko i imi: KOWALSKA Maria
Rozdzia 1. i Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java
19
Inicjay: MK Login: KOmar
Wielkoci liter na wydruku powinny by zgodne z przykadem, niezalenie od tego, jakie wielkoci liter wykorzysta uytkownik, podajc imi i nazwisko. Wypisz bdy, które powstan podczas uruchomienia aplikacji z niewaciw liczb parametrów.
Zadanie 5.3. Napisz program (plik ródowy: ArgsWspak.java), który uruchomiony z kilkoma argumentami wypisze list argumentów, oddzielonych odstpami, w odwrotnej kolejnoci.
Zadanie 5.4. Napisz program (plik ródowy: ArgWspak.java), który uruchomiony z kilkoma argumentami wypisze kady argument w odrbnym wierszu, odwracajc przy tym kolejno znaków w argumencie. Naley uy dwóch ptli, stosujc tzw. zagniedanie ptli. Zewntrzna ptla powinna odczyta kolejno wszystkie argumenty, a wpisana w jej ciele wewntrzna ptla ma za zadanie odwróci kolejno znaków w biecym argumencie.
Zadanie 5.5. Napisz program, który wywietli na ekranie etykietk zawierajc imi i nazwisko podane jako parametry wywoania aplikacji (plik ródowy: EtykietaArg.java). Zmodyfikuj odpowiednio rozwizanie zadania 2.4. Oblicz dugo tekstu (imienia i nazwiska razem z odstpem midzy nimi), liczb odstpów pomidzy midzy znakiem * a tekstem oraz po tekcie przed znakiem *. Stosown liczb odstpów moesz wywietli w ptli lub wyci jako podacuch z acucha zoonego z okrelonej liczby odstpów. Ze wzgldu na konieczno oblicze zadanie wyprzedza nieco omawian teori.
6. Prawda czy fasz — logiczny typ danych Prosty typ danych boolean moe przyjmowa jedn z dwóch wartoci: false (fasz) i true (prawda). Te dwie wartoci su do oceny logicznej rónych zda (warunków) i s podstaw do dziaania instrukcji sterujcych przebiegiem programu (instrukcji warunkowych, instrukcji wyboru i ptli). Klasa Boolean opakowuje prosty typ boolean.
20
Programowanie w jzyku Java
Zadanie 6.1. Napisz program, który w formie tabeli przedstawi dziaanie operatorów logicznych (plik ródowy: OperatoryLogiczne.java). Moesz zbudowa dwuelementow tablic wartoci logicznych i uy ptli typu for each do pobierania wartoci z tej tablicy. Dziki zagniedeniu ptli moesz w atwy sposób przetestowa wszystkie wartoci dla dwóch i wikszej liczby zda logicznych. Do dyspozycji masz trzy operatory: ! — negacj (NOT), & lub && — koniunkcj (iloczyn logiczny, AND), | lub || — alternatyw (sum logiczn, OR).
Zadanie 6.2. Napisz program (plik ródowy: PrawaLogiczne.java), który w formie tabeli przedstawi dowód nastpujcych praw logicznych: a) prawo wyczonego rodka p p , b) prawo niesprzecznoci p p , c) prawo podwójnego przeczenia p p . W zapisie matematycznym wyrae logicznych zastosowano nastpujce symbole: — negacja, — koniunkcja, — alternatywa, — równowano . Równowano moemy w programie zastpi operatorem jest równe (== — dwa znaki równoci obok siebie). Wynikiem porównania dwóch wartoci nalecych do typu prostego jest warto logiczna.
Zadanie 6.3. Napisz program (plik ródowy: PrawaDeMorgana.java), który w formie tabeli przedstawi dowód praw De Morgana: a) I prawo De Morgana — prawo zaprzeczenia koniunkcji
p q p q ,
b) II prawo De Morgana — prawo zaprzeczenia alternatywy
p q p q .
Zadanie 6.4. Napisz program, który przedstawi tabel wartoci logicznych implikacji (plik ródowy: Implikacja.java).
Rozdzia 1. i Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java
21
Przyjmijmy, e wartoci logiczne s uporzdkowane i false poprzedza true. Implikacja jest faszywa tylko w jednym przypadku true false (z prawdziwych zaoe nie mona udowodni tezy faszywej), w pozostaych przypadkach jest prawdziwa (z prawdy wynika prawda, na podstawie faszywych zaoe mona udowodni zarówno prawd, jak i fasz). Zauwamy, e stosujc operator mniejsze lub równe ( p q r @ > p q p r @ ,
c) prawo rozdzielnoci koniunkcji wzgldem alternatywy
> p q r @ > p q p r @ , d) prawo odrywania > p q q @ q , e) prawo eliminacji implikacji p q p q .
W prawach zawierajcych implikacj (podpunkty a), d) i e)) skorzystaj z metody statycznej impl(), zdefiniowanej w rozwizaniu zadania 6.4. Uproci to w istotny sposób zapis zadania. Mona te wprowadzi dodatkowe zmienne typu boolean, przechowujce wartoci wyrae stojcych po lewej i prawej stronie badanych równowanoci.
22
Programowanie w jzyku Java
Zadanie 6.7. W klasie String (od wersji Javy 1.6) dostpna jest metoda isEmpty(), zwracajca warto true, gdy dugo acucha znaków jest równa 0, oraz warto false w pozostaych przypadkach. Napisz prost aplikacj (plik ródowy: StringIsEmpty.java) pokazujc dziaanie tej metody. Ustal warto acucha, a nastpnie wywietl na ekranie ten acuch, jego dugo i warto zwrócon przez metod isEmpty().
Zadanie 6.8. Napisz program (plik ródowy: TestChar.java) demonstrujcy dziaanie metod isDigit(), isLetter(), isLetterOrDigit(), isLowerCase(), isSpaceChar(), isUpperCase() i isWhiteSpace(). Wyniki przedstaw w postaci tabeli. Zadanie wykonaj dla zestawu znaków zapisanego w acuchu: a) "A\240b3&4\040", b) "o 0+\t", c) "#\"\304\\\344\b\n".
7. Liczby cakowite typu int i klasa Integer Prosty typ danych int pozwala na przechowywanie czterobajtowych (32-bitowych) liczb cakowitych ze znakiem. Klasa Integer opakowuje prosty typ int i oferuje dwa konstruktory budujce obiekt na podstawie liczby cakowitej lub acucha znaków. Zawiera m.in. szereg metod przeznaczonych do konwersji obiektów klasy Integer na inne typy liczbowe lub acuchy znaków.
Zadanie 7.1. Uruchom aplikacj, której kod ródowy przedstawiono na listingu 4. Na podstawie obserwacji wyników dziaania programu opisz przeznaczenie uytych staych i metod statycznych klasy Integer. W kodzie ródowym programu, w miejscu trzech kropek, wpisz odpowiednie teksty objaniajce wywietlane wyniki. W przypadku wtpliwoci zajrzyj do dokumentacji jzyka Java (np. http://download.oracle.com/javase/1.5.0/ docs/api/java/lang/Integer.html). Listing 4. StaticInteger.java public class StaticInteger { public static void main(String args[]) { System.out.println("Wybrane stae i metody statyczne klasy Integer\n");
Rozdzia 1. i Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java
23
System.out.println("...: "+Integer.MIN VALUE); System.out.println("...: "+Integer.MAX VALUE); System.out.println("...: "+Integer.SIZE); int a = 179; System.out.println("a = "+a); System.out.println("...: "+Integer.toBinaryString(a)); System.out.println("...: "+Integer.toOctalString(a)); System.out.println("...: "+Integer.toHexString(a)); System.out.println("...: "+Integer.toString(a)); System.out.println("...: "+Integer.toString(a, 4)); int b = Integer.parseInt(" 177"); System.out.println("b = "+b); int c = Integer.parseInt("1000", 8); System.out.println("c = "+c); System.out.println("...: "+Integer.signum(a)); System.out.println("...: "+Integer.signum(b)); System.out.println("...: "+Integer.signum(0)); } }
Zadanie 7.2. Uruchom aplikacj przedstawion na listingu 5. Na podstawie uzyskanych wyników i dokumentacji objanij (w postaci komentarza) uyte metody klasy Integer. Listing 5. ObjectInteger.java public class ObjectInteger { public static void main(String args[]) { System.out.println("Wybrane metody obiektów klasy Integer\n"); /* tworzenie obiektów */ Integer a = new Integer(1024); Integer b = new Integer("02000"); Integer c = Integer.decode("02000"); Integer d = Integer.decode("0x2000"); System.out.println("a = "+a); System.out.println("b = "+b); System.out.println("c = "+c); System.out.println("d = "+d); /* porównania obiektów */ System.out.println("...? "+a.equals(b)); System.out.println("...? "+a.equals(c)); System.out.println("...? "+a.compareTo(c)); System.out.println("...? "+c.compareTo(d)); System.out.println("...? "+d.compareTo(c)); /* zmiana wartoci obiektu */ a = Integer.valueOf(1000); b = Integer.valueOf("1000"); c = Integer.valueOf("1000", 2); d = Integer.valueOf("1000", 16); System.out.println("a = "+a); System.out.println("b = "+b); System.out.println("c = "+c); System.out.println("d = "+d); } }
24
Programowanie w jzyku Java
Zmienne i stae (literay) typu int mog by wykorzystane do wykonywania oblicze w zbiorze liczb cakowitych, w zakresie ograniczonym 32-bitowym rozmiarem typu (od –231 do 231–1). Do dyspozycji mamy cztery podstawowe operatory: dodawanie +, odejmowanie –, mnoenie * i dzielenie (cakowite) / oraz operator %, sucy do obliczania reszty z dzielenia dwóch liczb cakowitych. Warto cakowit (potrzebn do oblicze) zawart w obiekcie moemy uzyska przy uyciu metody intValue().
Zadanie 7.3. Dla dwóch dowolnie wybranych liczb cakowitych typu int napisz aplikacj pokazujc dziaanie operatora + (plik ródowy: Dodawanie.java). Wynik wywietlaj w postaci: a = 3, b = 15 a + b = 18
Zadeklaruj i zainicjuj dwie zmienne typu int, np. int a = 2451, b = 375;. Wyraenia wykonujce obliczenia moesz umieci jako parametry w metodzie println().
Zwró uwag na kolejno wykonywania dziaa, gdy operatora + uywasz do oblicze i czenia tekstów!
Zadanie 7.4. Dla dwóch dowolnie wybranych liczb cakowitych typu int napisz aplikacje pokazujce dziaanie pozostaych operatorów arytmetycznych: a) odejmowanie – (plik ródowy: Odejmowanie.java), b) mnoenie * (plik ródowy: Mnoenie.java), c) dzielenie / (plik ródowy: Dzielenie.java), d) reszta z dzielenia % (plik ródowy: Reszta.java).
Wyniki wywietlaj podobnie jak w zadaniu 7.3.
Zadanie 7.5. Napisz aplikacj (plik ródowy: Dzielenie2.java) demonstrujc dzielenie z reszt dla liczb cakowitych o rónych znakach. Wyniki wywietlaj w postaci znanej z lekcji matematyki, np. 13 : 2 = 6 r. 1.
Zadanie 7.6. Napisz aplikacj (plik ródowy: Suma.java), która obliczy sum dwóch liczb naturalnych podanych jako parametry wywoania. Wynik wywietl na ekranie. Parametry s przekazywane do programu jako acuchy znaków. Potrzebna bdzie zamiana acucha na liczb cakowit. Mona uy odpowiedniej metody statycznej lub posuy si obiektami klasy Integer.
Rozdzia 1. i Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java
25
Zadanie 7.7. Napisz aplikacj (plik ródowy: Sumuj.java), która obliczy sum serii liczb naturalnych podanych jako parametry wywoania aplikacji. Wynik wywietl na ekranie. Wprowad zmienn suma typu int i zainicjuj j wartoci 0. Korzystajc z ptli typu for each, przegldaj tablic argumentów, zamieniaj argument (acuch znaków) na liczb cakowit i dodawaj j do sumy. Po przejrzeniu caej tablicy wywietl wynik.
Zadanie 7.8. Napisz aplikacj (plik ródowy: Zamiana.java), która na podstawie dwóch parametrów cakowitych — podstawy systemu liczbowego od 2 do 36 i liczby dziesitnej — wywietli na ekranie liczb zapisan we wskazanym systemie wedug podanego wzoru: 102[10] = 123[9].
Zadanie 7.9. Napisz aplikacj (plik ródowy: Zamiana2.java), która na podstawie dwóch parametrów — podstawy systemu liczbowego od 2 do 36 i liczby zapisanej w systemie o podstawie podanej jako pierwszy parametr — wywietli na ekranie t liczb zapisan w systemie dziesitnym wedug podanego wzoru: 123[9] = 102[10].
8. Inne typy liczb cakowitych w Javie Do zapisywania liczb cakowitych w pamici komputera najczciej uywamy 1, 2, 4 lub 8 bajtów (odpowiednio 8, 16, 32 lub 64 bitów). Odpowiada to nastpujcym typom liczb cakowitych ze znakiem w jzyku Java: byte, short, int lub long. Z kadym z wymienionych typów prostych zwizana jest klasa opakowujca — Byte, Short, Integer lub Long. Klasy te dziedzicz z klasy abstrakcyjnej java.lang.Number. Zmianie ulegaj jedynie zakresy dostpnych wartoci, natomiast metody maj identyczne nazwy i analogiczny sposób dziaania. Kada z wymienionych klas posiada metody zwracajce warto reprezentowan przez obiekt jako warto jednego z pozostaych typów cakowitych.
Zadanie 8.1. Przepisz i uruchom kod ródowy przedstawiony na listingu 6. Opisz krótko zastosowane metody. Uzasadnij otrzymane rezultaty. Powtórz wiczenie, zmieniajc warto liczby n na minimaln dostpn warto typu long. Listing 6. LongNumber.java public class LongNumber { public static void main(String args[]) { long n = Long.MAX VALUE;
26
Programowanie w jzyku Java System.out.println("n = "+n); System.out.println("BIN: "+Long.toBinaryString(n)); System.out.println("HEX: "+Long.toHexString(n)); long m = n+1; System.out.println("m = "+m); System.out.println("BIN: "+Long.toBinaryString(m)); System.out.println("HEX: "+Long.toHexString(m)); Long max = new Long(n); System.out.println("Zamiana na typ int, m = "+max.intValue()); System.out.println("BIN: "+ Integer.toBinaryString(max.intValue())); System.out.println("HEX: "+Integer.toHexString(max.intValue())); System.out.println("Zamiana na typ int, m = "+(int)m); System.out.println("BIN: "+Integer.toBinaryString((int)m)); System.out.println("HEX: "+Integer.toHexString((int)m)); } }
Zadanie 8.2. Napisz program (plik ródowy: MinMax.java) wywietlajcy minimalne i maksymalne wartoci liczb cakowitych typu byte, short, int i long. Wyniki wywietl w postaci: nazwa typu . Wykorzystaj stae MIN VALUE i MAX VALUE z klas opakowujcych typy proste.
Zadanie 8.3. Napisz program (plik ródowy: MaxPositive.java) wywietlajcy maksymalne wartoci liczb cakowitych typu byte, short, int i long. Wyniki wywietl w postaci binarnej i szesnastkowej. Klasy opakowujce Integer i Long zawieraj metody toBinaryString() i toHexString() — tych metod nie ma w klasach Byte i Short.
Zadanie 8.4. Napisz program (plik ródowy: Kodowanie.java) zamieniajcy acuch znaków (np. sowo kodowanie) na cig bajtów odpowiadajcych tym znakom. Poszukaj odpowiedniej metody w klasie String.
Zadanie 8.5. Napisz program (plik ródowy: Dekodowanie.java) zamieniajcy cig bajtów (np. {115, 122, 121, 102, 114}) na acuch znaków odpowiadajcych tym liczbom.
Rozdzia 1. i Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java
27
Jeden z konstruktorów klasy String tworzy acuch znaków na podstawie tablicy bajtów.
Zadanie 8.6. Napisz program (plik ródowy: DodajCyfry.java) obliczajcy sum cyfr liczby cakowitej dodatniej podanej: a) w postaci tekstu — acucha znaków (cyfr) reprezentujcych t liczb, b) jako warto typu long. Skorzystaj z rozwizania zadania 8.4 i pamitaj, e kody cyfr s równe: 0 — 48, 1 — 49, 2 — 51 itd. Liczb moesz zamieni na acuch znaków.
Zadanie 8.7. Napisz program (plik ródowy: Txt2Hex.java) zamieniajcy acuch znaków ASCII na acuch cyfr szesnastkowych odpowiadajcych tym znakom. Zamie tekst na cig bajtów, a nastpnie przedstaw bajty w postaci szesnastkowej. Na jeden bajt (znak ASCII) przypadn dwie cyfry szesnastkowe.
Zadanie 8.8. Napisz program (plik ródowy: Hex2Txt.java) zamieniajcy acuch cyfr szesnastkowych na odpowiadajcy mu acuch znaków ASCII (dwie cyfry przypadaj na jeden znak).
9. Typy liczb zmiennoprzecinkowych Typy zmiennoprzecinkowe su do przechowywania liczb z czci uamkow. Java oferuje dwa typy zmiennoprzecinkowe zgodne ze standardem IEEE 754: float — dane zmiennoprzecinkowe 32-bitowe pojedynczej precyzji
o dokadnoci 7 – 8 cyfr znaczcych, double — dane zmiennoprzecinkowe 64-bitowe podwójnej precyzji
o dokadnoci 15 cyfr znaczcych.
Zadanie 9.1. Przepisz i uruchom kod ródowy przedstawiony na listingu 7. Zobacz efekty dziaania programu. Czy na podstawie zapisu kodu ródowego (bez czytania dokumentacji) moesz okreli dziaanie uytych metod? Sporzd krótki opis kodu i efektów jego dziaania.
28
Programowanie w jzyku Java
Listing 7. DemoDouble.java public class DemoDouble { public static void main(String[] args) { double a = Double.MIN VALUE; System.out.println("Minimalna warto dodatnia: "+a); System.out.println("BIN: "+Long.toBinaryString(Double. doubleToLongBits(a))); System.out.println("HEX: "+Double.toHexString(a)); a = a; System.out.println("Liczba przeciwna: "+a); System.out.println("BIN: "+Long.toBinaryString(Double. doubleToLongBits(a))); System.out.println("HEX: "+Double.toHexString(a)); } }
Zadanie 9.2. Przedstaw w postaci sowa 64-bitowego reprezentacj binarn kilku wybranych liczb typu double (plik ródowy: DoubleBin.java). Z cigu 64 bitów wyodrbnij bit znaku, cech i mantys. a) 0,25; 0,5; 1,0; 2,0; 512,0; b) 0,01; 0,1; 1,0; 10,0; 100,0; c) 1,367; 1367; 13,67; –13,67; 1,367e–12; 1,367e12; d) symbole specjalne: Double.NaN (ang. Not-a-Number), np. wynik pierwiastkowania liczby ujemnej, Double.NEGATIVE INFINITY ( f — ujemna nieskoczono, np. wynik dzielenia –1/0,0), Double.POSITIVE INFINITY ( f
— dodatnia nieskoczono, np. wynik dzielenia 1/0,0). e) dwie reprezentacje zmiennoprzecinkowe zera 0.0 i –0.0 oraz wartoci ekstremalne Double.MIN VALUE, Double.MAX VALUE i 2.2250738585072014e-308. Moemy zastosowa metod statyczn doubleToLongBits() z klasy Double i zamieni liczb zmiennoprzecinkow typu double na liczb cakowit typu long o identycznej reprezentacji binarnej. W dalszej kolejnoci zamienimy liczb typu long na odpowiadajcy jej cig cyfr binarnych. Niestety, metoda statyczna toBinaryString() z klasy Long, tworzc cig cyfr binarnych odpowiadajcych liczbie typu long, pomija zera nieznaczce. Uzupenimy te zera do 64 znaków w acuchu, wycinajc je jako podcig o odpowiedniej dugoci z cigu (acucha) zoonego z 64 cyfr 0 i dodajc do cigu zer uzyskan posta binarn liczby. Musimy pamita , e indeksy znaków w acuchu s liczone od strony lewej do prawej, natomiast bity w liczbie binarnej s numerowane od strony prawej (najmodszy bit to 0) do lewej (najstarszy bit to 63). Znaczenie poszczególnych bitów w reprezentacji binarnej liczby typu double jest nastpujce: bit nr 63 — bit znaku, bity o numerach od 52 do 62 — cecha liczby (11 bitów), bity o numerach od 0 do 51 (52 bity) — cz uamkowa mantysy.
Rozdzia 1. i Pierwszy krok — rozpoczynamy nauk programowania w jzyku Java
29
Zadanie 9.3. Cig bitów 111110000011110000111000110010 reprezentuje pewn liczb zmiennoprzecinkow pojedynczej precyzji (zera nieznaczce pominito). Jak warto dziesitn ma ta liczba? Napisz program (plik ródowy: Bin2Float.java) wyznaczajcy t warto. Liczby typu int i float zajmuj w pamici 32 bity. Znajd liczb cakowit posiadajc podan reprezentacj binarn i skorzystaj z metody intBitsToFloat() z klasy Float.
Zadanie 9.4. Cig bitów 111110000011110000111000110010 reprezentuje pewn liczb zmiennoprzecinkow podwójnej precyzji (zera nieznaczce pominito). Jak warto dziesitn ma ta liczba? Napisz program (plik ródowy: Bin2Double.java) wyznaczajcy t warto. Liczby typu long i double zajmuj w pamici 64 bity.
Zadanie 9.5. Napisz binarne reprezentacje symboli specjalnych ( rf , NaN) dla liczb zmiennoprzecinkowych pojedynczej precyzji. Utwórz aplikacj (plik ródowy: TestBinFloat.java), która odkoduje liczb binarn podan jako parametr wywoania i wywietli odpowiadajc jej warto typu float. Wykorzystaj t aplikacj do sprawdzenia poprawnoci swoich odpowiedzi. Reprezentacja binarna liczby zmiennoprzecinkowej pojedynczej precyzji skada si z bitu znaku, 8 bitów cechy i 23 bitów mantysy (razem 32 bity). Cecha symbolu specjalnego ma wszystkie bity równe 1.
30
Programowanie w jzyku Java
Rozdzia 2.
Drugi krok — operacje wejcia-wyjcia i instrukcje sterujce w Javie 10. Wywietlanie sformatowanych wyników w konsoli. Stae i metody z klasy Math Do formatowania wywietlanych wyników w konsoli moemy uy metody printf() na obiekcie out klasy System: System.out.printf(acuch formatujcy, lista argumentów);
Pierwszy parametr (acuch formatujcy) jest acuchem znaków (obiektem klasy String) zawierajcym znaczniki formatujce w postaci: %[indeks argumentu$][flaga][szeroko][.precyzja]znak konwersji
Drugi parametr (lista argumentów) jest list zmiennych lub staych oddzielonych przecinkami — wartoci tych argumentów bd podstawiane w miejsce znaczników formatujcych w acuchu formatujcym zgodnie z kolejnoci wystpowania lub w miejscu okrelonym przez opcjonalny indeks argumentu$. Pozostae opcjonalne parametry okrelaj: flaga — znak okrelajcy dodatkowe cechy sformatowanego wyniku, np. + oznacza, e przed liczb zawsze wywietlany jest znak + lub –.
32
Programowanie w jzyku Java szeroko — okrela szeroko pola, czyli liczb znaków przeznaczonych
do wywietlenia wartoci argumentu (jeli warto nie mieci si w tym polu, to jego rozmiar zostanie automatycznie poszerzony). precyzja — okrela liczb miejsc po przecinku (domylnie 6) dla wywietlanych
liczb zmiennoprzecinkowych. Znacznik formatujcy rozpoczyna si znakiem % i koczy (obowizkowym) znakiem (znak konwersji) okrelajcym typ formatowanych danych, np.: c — znak, d — liczba cakowita dziesitna, f — liczba zmiennoprzecinkowa, s — acuch znaków. Wicej szczegóów znajdziemy w dokumentacji klasy Formater: http://docs.oracle.com/ javase/1.5.0/docs/api/java/util/Formatter.html. Klasa Math zawiera zestaw funkcji matematycznych i dwie stae (pola klasy) — przyblienie liczby S i podstawy logarytmu naturalnego e. Wszystkie funkcje zostay zdefiniowane jako metody statyczne, wic nie tworzymy obiektów klasy Math, a jedynie wywoujemy zdefiniowane metody, np. Math.sqrt(2) zwróci warto (przyblion) pierwiastka kwadratowego z liczby 2. Wykaz funkcji znajdziemy w dokumentacji: http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html.
Zadanie 10.1. Przedstaw uamek
4 7
z dokadnoci do 5 miejsc po przecinku.
Dzielc 4 przez 7, otrzymasz uamek dziesitny, o ile co najmniej jedn z tych liczb zamienisz na liczb zmiennoprzecinkow, np. stosujc tzw. rzutowanie double x = (double) 4. Do sformatowania wyniku moesz uy metody System.out.printf().
Zadanie 10.2. Wywietl w konsoli z dokadnoci do 10 miejsc po przecinku nastpujce liczby niewymierne: e, S i M (liczba Fibonacciego). Liczby poprzed komentarzem sownym i ustaw w kolumnie wyrównanej do prawej strony. Liczby e i S s zdefiniowane w klasie Math jako stae, natomiast M
1 5 . 2
Zadanie 10.3. Napisz aplikacj, która wywietli w konsoli w trzech kolumnach liczby naturalne 2, 3, 5, 7, 11, 13 i 17, pierwiastki kwadratowe i pierwiastki szecienne z tych liczb. Wartoci pierwiastków wywietlaj z dokadnoci do 8 miejsc po przecinku, w kolumnach o szerokoci 15 znaków. Liczby 2, 3, 5, 7, 11, 13 i 17 umie w tablicy. Zastosuj ptl typu for each do przegldania tablicy, oblicze i wywietlania pierwiastków.
Rozdzia 2. i Drugi krok — operacje wejcia-wyjcia i instrukcje sterujce w Javie
33
Zadanie 10.4. Napisz aplikacj, która wywietli w konsoli pierwiastki arytmetyczne od stopnia 2. do 10. z liczby 5 z dokadnoci do 6 miejsc po przecinku. 1
Zgodnie z definicj n x x n , wic do obliczania pierwiastków mona wykorzysta metod Math.pow(podstawa, wykadnik).
Zadanie 10.5. Wywietl w konsoli kody ósemkowe, dziesitkowe i szesnastkowe wielkich liter alfabetu aciskiego. W pierwszym wierszu umie opisy poszczególnych kolumn: Znak, OCT, DEC i HEX. Wykorzystaj specyfikatory %o, %d i %x w acuchu formatujcym.
Zadanie 10.6. Wywietl w konsoli miar kta o rozwartoci 1 radiana w stopniach (z maksymaln moliw precyzj), w stopniach i minutach ktowych oraz w stopniach, minutach i sekundach ktowych. W klasie Math znajdziesz metody zamieniajce radiany na stopnie i stopnie na radiany. Pozostaje opracowa samodzielnie zamian czci dziesitnych stopnia na minuty (1° = 60') i sekundy ktowe (1' = 60").
Zadanie 10.7. Wywietl w konsoli miary któw 1°, 1' i 1" w radianach z dokadnoci do 15 miejsc po przecinku.
Zadanie 10.8. Oblicz kty ostre w trójkcie egipskim (trójkcie prostoktnym o proporcji boków 3:4:5). Wyniki podaj: a) w radianach, z dokadnoci do 4 miejsc po przecinku, b) w stopniach, z dokadnoci do 1 miejsca po przecinku, c) w stopniach i minutach ktowych, z dokadnoci do 1', d) w stopniach, minutach i sekundach ktowych z dokadnoci do 1". W klasie Math znajdziesz funkcje trygonometryczne (argumenty w radianach) oraz funkcje do nich odwrotne (wartoci w radianach).
34
Programowanie w jzyku Java
11. Wczytywanie danych — klasa Scanner Pobieranie danych ze standardowego strumienia wejciowego System.in moemy zrealizowa za pomoc obiektu klasy Scanner: Scanner input = new Scanner(System.in);
Klasa Scanner oferuje m.in. metody testujce, czy w strumieniu znajduje si kolejny token okrelonego typu, oraz metody odczytujce jego warto ze strumienia: hasNextLine() — zwraca warto true, gdy w strumieniu znajduje si wiersz danych, w przeciwnym wypadku zwraca warto false; nextLine() — odczytuje jeden wiersz danych; hasNext() — zwraca warto true, gdy w strumieniu znajduje si nastpny
token (np. sowo ograniczone spacjami); next() — odczytuje ze strumienia jeden token (jedno sowo); hasNextInt() — zwraca warto true, gdy kolejny token w strumieniu
reprezentuje liczb cakowit; nextInt() — odczytuje ze strumienia kolejny token, interpretujc go jako
liczb cakowit. Podobne metody zdefiniowano dla pozostaych prostych typów danych. Szczegóowe informacje znajdziemy w dokumentacji pod adresem http://docs.oracle.com/javase/ 1.5.0/docs/api/java/util/Scanner.html.
Zadanie 11.1. Napisz program zamieniajcy temperatur podan w stopniach Celsjusza na temperatur wyraon w stopniach Fahrenheita. Dane wejciowe wprowadzamy z klawiatury w postaci liczby dziesitnej; wynik naley obliczy i wywietli z dokadnoci do 0,1 stopnia. Wzór do zamiany temperatury ze skali Celsjusza na skal Fahrenheita: °F = °C·1,8+32.
Zadanie 11.2. Napisz program zamieniajcy temperatur podan w stopniach Fahrenheita na temperatur wyraon w stopniach Celsjusza. Dane wejciowe wprowadzamy z klawiatury w postaci liczby cakowitej, wynik naley obliczy i wywietli z dokadnoci do 0,1 stopnia. Przekszta wzór podany w zadaniu 11.1.
Rozdzia 2. i Drugi krok — operacje wejcia-wyjcia i instrukcje sterujce w Javie
35
Zadanie 11.3. Napisz program obliczajcy dugo przeciwprostoktnej w trójkcie prostoktnym, majc dane: a) dugoci przyprostoktnych, b) dugo przyprostoktnej i miar kta ostrego (podan w stopniach) lecego
naprzeciw tej przyprostoktnej. Dane uytkownik wprowadza z klawiatury. Wyniki naley wywietli z dokadnoci do 0,001.
Zadanie 11.4. Napisz program, który odczyta z konsoli dwie liczby zapisane w naturalnym kodzie binarnym, obliczy ich sum i wywietli wynik w postaci binarnej. Zaproponuj ograniczenie liczby cyfr binarnych stosownie do przyjtej metody oblicze i uytych zmiennych. Odczytaj cigi cyfr binarnych i zamie je na liczby cakowite, dodaj uzyskane rezultaty i przedstaw wynik w postaci binarnej. Póniej wykonamy te obliczenia na cigach cyfr, bez konwersji na liczby.
Zadanie 11.5. Napisz program, który zamieni uamek zwyky na procent. Uamek zwyky wprowadzamy z klawiatury w postaci acucha znaków zoonego z dwóch liczb cakowitych (licznika i mianownika) oddzielonych znakiem / (bez odstpów). Wynik naley wywietli z dokadnoci do 0,1%.
Zadanie 11.6.
acuch znaków zawiera oddzielone odstpami imi i nazwisko pracownika, liczb przepracowanych godzin i stawk godzinow. Napisz program obliczajcy na tej podstawie wynagrodzenie nalene pracownikowi. Wykorzystaj metody klasy Scanner do przeczytania danych z acucha znaków.
Zadanie 11.7. Plik tekstowy dane.txt zawiera wiersz tekstu, a w nim oddzielone odstpami imi i nazwisko pracownika, liczb przepracowanych godzin i stawk godzinow. Napisz program obliczajcy na tej podstawie wynagrodzenie nalene pracownikowi. Wykorzystaj metody klasy Scanner do przeczytania danych z pliku tekstowego.
36
Programowanie w jzyku Java
12. Operacje na tekstach — klasy StringBuffer i StringBuilder Skadanie acucha znaków z krótszych acuchów moemy zrealizowa przy uyciu obiektu klasy StringBuffer lub StringBuilder (od wersji JDK 5.0). Obie klasy maj ten sam interfejs. Podstawowe metody to: append() (dodawanie znaków na kocu acucha — dane rónych typów s konwertowane na typ String i doczane do budowanego obiektu), delete() (usuwanie znaków z acucha), insert() (wstawianie znaków do acucha), replace() (zastpowanie znaków w acuchu). W budowanym obiekcie mamy dostp do odczytu pojedynczych znaków (metoda charAt()) i podacuchów (metoda substring()) oraz moliwo zmiany pojedynczego znaku (setCharAt()). Wicej informacji mona znale w dokumentacji: http://docs.oracle.com/javase/1.5.0/ docs/api/java/lang/StringBuffer.html.
Zadanie 12.1. Wykresem funkcji kwadratowej f ( x) ax 2 bx c, a z 0 jest parabola o wierzchoku § b ' · . Napisz program, który obliczy i wywietli w konsoli wspórzdne wierz, ¸ ¨ © 2 a 4a ¹
choka paraboli. Zakadamy, e uytkownik bdzie podawa poprawne wspóczynniki trójmianu. Wykorzystaj obiekt klasy StringBuffer lub StringBuilder i metod append() do zbudowania acucha znaków przedstawiajcego wspórzdne wierzchoka. Metoda append() dodaje na kocu acucha znaki, acuchy znaków, wartoci wbudowanych typów danych zamienione na acuch znaków lub obiekty zamienione na acuch znaków.
Zadanie 12.2. Rozwi zadanie 12.1, stosujc obiekt i metod insert() klasy StringBuffer lub StringBuilder. Zacznij od zbudowania acucha znaków "(, )", do którego nastpnie wstawisz obliczone wartoci wspórzdnych wierzchoka paraboli. Zwró uwag na kolejno wstawiania tych wartoci do pocztkowego acucha.
Rozdzia 2. i Drugi krok — operacje wejcia-wyjcia i instrukcje sterujce w Javie
37
Zadanie 12.3. Rozwi zadanie 12.1, stosujc obiekt i metod replace() klasy StringBuffer lub StringBuilder. Zacznij od zbudowania acucha znaków "(#1, #2)". Podacuchy "#1" i "#2" (o dugoci 2 znaków) wskazuj miejsca, w których zastpisz te podacuchy obliczonymi wartociami wspórzdnych wierzchoka paraboli. Aby znale miejsca wstawiania obliczonych wartoci, zastosuj metod indexOf().
Zadanie 12.4. Napisz program, który obliczy rónic liczby cakowitej dodatniej wprowadzonej z konsoli i liczby zapisanej tymi samymi cyframi w odwrotnej kolejnoci. Wynik wywietl w postaci caego wyraenia, np.: 452-254 = 198. W klasie StringBuffer lub StringBuilder znajdziesz metod reverse() odwracajc kolejno znaków w acuchu oraz metod toString() konwertujc budowany acuch na obiekt klasy String.
Zadanie 12.5. Symbol [a, b] w geometrii analitycznej oznacza wektor o wspórzdnych a i b (w przestrzeni dwuwymiarowej, czyli na paszczy nie). Napisz program obliczajcy dugo wektora [a, b] wprowadzonego przez uytkownika z klawiatury w postaci acucha znaków, np. [2.5, -4]. Zakadamy, e uytkownik bdzie podawa poprawn posta danych (nawiasy prostoktne, przecinek i liczby dziesitne w notacji z kropk). Z acucha znaków naley wydoby podacuchy reprezentujce liczby a i b (wspórzdne wektora), zamieni je na liczby i obliczy dugo wektora ze wzoru
u
a2 b2 .
Zadanie 12.6. Napisz program obliczajcy dugo wektora [a, b, c] (w przestrzeni trójwymiarowej) wprowadzonego przez uytkownika z klawiatury w postaci acucha znaków. Zakadamy, e uytkownik bdzie podawa poprawn posta danych (nawiasy prostoktne, dwa przecinki oddzielajce wspórzdne i trzy liczby dziesitne w notacji z kropk).
Dugo wektora obliczymy ze wzoru u
a 2 b2 c2 .
Rozdzia 2. i Drugi krok — operacje wejcia-wyjcia i instrukcje sterujce w Javie
39
Zadanie 13.1. Napisz program, który zapyta uytkownika o imi, a nastpnie wykorzystujc podane imi, wywietli w konsoli napis w postaci: "Jan jest mczyzn." lub "Anna jest kobiet.". Wykorzystaj fakt, e typowe polskie imiona eskie s zakoczone na liter a.
Zadanie 13.2. Napisz program obliczajcy pole powierzchni i obwód kwadratu. Dugo boku kwadratu uytkownik wprowadzi z klawiatury. Program powinien sprawdzi, czy wprowadzona dugo boku jest poprawna (dodatnia).
Zadanie 13.3. Uytkownik wprowadza z klawiatury dwie liczby rzeczywiste a i b. Napisz program, który wywietli (zapisany w sposób symboliczny) zbiór zoony z tych liczb oraz wszystkich liczb zawartych midzy nimi. Jeli liczby s równe, to otrzymamy zbiór jednoelementowy {a}, w przeciwnym razie szukanym zbiorem bdzie przedzia domknity.
Zadanie 13.4. Uytkownik wprowadza z klawiatury wspóczynniki funkcji kwadratowej f ( x)
ax 2 bx c
Napisz program, który wyznaczy zbiór wartoci tej funkcji lub wywietli komunikat, e podane wspóczynniki nie s poprawne (przypadek a 0 ). Do zapisania zbioru wartoci funkcji, który jest przedziaem nieograniczonym, bdzie potrzebny symbol f . W konsoli moemy ten symbol „zoy ” z dwóch znaków oo, co w poczeniu ze znakiem + lub — bdzie wystarczajco czytelne (–oo lub +oo).
Zadanie 13.5. Uytkownik wprowadza z klawiatury wspóczynniki funkcji kwadratowej f ( x)
ax 2 bx c
Napisz program, który wyznaczy przedziay monotonicznoci i ekstremum tej funkcji.
40
Programowanie w jzyku Java
Zadanie 13.6. Napisz program rozwizujcy równanie liniowe ax b 0 . Wspóczynniki równania uytkownik wprowadzi z klawiatury. Rozwa wszystkie moliwe przypadki dla wspóczynników równania.
Zadanie 13.7. Uytkownik wprowadza z klawiatury trzy liczby a, b i c. Napisz program, który wywietli najmniejsz (lub najwiksz) z tych liczb. Nie wprowadzaj dodatkowych zmiennych.
Zadanie 13.8. Uytkownik wprowadza z klawiatury trzy liczby a, b i c. Napisz program, który wywietli te liczby w sposób uporzdkowany, w kolejnoci od najmniejszej do najwikszej (lub od najwikszej do najmniejszej). Nie wprowadzaj dodatkowych zmiennych.
Zadanie 13.9. Stosujc instrukcj selekcji, napisz program, który liczb naturaln jednocyfrow zapisze sownie.
Zadanie 13.10. Napisz program, który podan liczb naturaln mniejsz od 100 zapisze sowami.
Zadanie 13.11. Napisz program, który podan liczb naturaln mniejsz od 1000 zapisze sowami.
Zadanie 13.12. Napisz program, który sprawdzi poprawno daty z obecnego wieku, zapisanej w postaci dd.mm.rrrr, i wywietli odpowiedni komunikat.
Zadanie 13.13. Napisz program, który dat podan w postaci dd.mm.rrrr zapisze w formacie rrrr-mm-dd. Przyjmij, e wprowadzana data jest poprawna (np. sprawdzona programem z zadania 13.12).
Zadanie 13.14. Napisz program, który dat podan w formacie dd.mm.rrrr zapisze w postaci tradycyjnej: a) z miesicem zapisanym sownie, np. 15 marca 2012; b) z miesicem zapisanym w systemie rzymskim, np. 15 III 2012.
Przyjmij, e wprowadzona przez uytkownika data jest poprawna.
Rozdzia 2. i Drugi krok — operacje wejcia-wyjcia i instrukcje sterujce w Javie
41
Zadanie 13.15. Napisz program, który na podstawie daty podanej w formacie dd.mm.rrrr okreli, jaki to dzie tygodnia. Przyjmij, e wprowadzona przez uytkownika data jest poprawna. Poszukaj informacji na temat wzoru Zellera.
14. Instrukcja ptli typu do-while Ptla ze sprawdzaniem warunku na kocu ma posta: do instrukcja; while(warunek);
Najpierw jest wykonywana instrukcja, potem obliczana jest warto wyraenia logicznego (warunek). Jeli warunek ma warto true, to powracamy do wykonywania instrukcji, i cykl si powtarza. Cech charakterystyczn tej ptli jest to, e instrukcja wykona si co najmniej raz (do instrukcja; while(false);). Naley zwróci uwag, aby instrukcja miaa wpyw na badany warunek, poniewa moemy uzyska ptl nieskoczon (do instrukcja; while(true);). Ptl nieskoczon, utworzon wiadomie, moemy przerwa, uywajc w ciele ptli instrukcji warunkowej i instrukcji break.
Zadanie 14.1. Uytkownik wprowadza z klawiatury seri liczb rónych od zera, zero natomiast jest sygnaem zakoczenia wprowadzania danych. Napisz program, który obliczy sum tych liczb.
Zadanie 14.2. Podczas wprowadzania danych niejednokrotnie potrzebujemy liczb speniajcych okrelone warunki, np. dodatnich. Napisz program, który przyjmie z konsoli wycznie warto dodatni zmiennej. Jeli uytkownik poda liczb ujemn lub zero, to program powinien ponowi danie podania waciwej wartoci. Wczytywanie wartoci zmiennej umie w ptli ze sprawdzaniem warunku na kocu.
Zadanie 14.3. Napisz program, który wywietli w konsoli wielokrotnoci liczby 7 mniejsze od 100.
42
Programowanie w jzyku Java
Zadanie 14.4. Napisz program obliczajcy pole powierzchni koa. Promie koa uytkownik wprowadza z klawiatury. Program powinien zasygnalizowa bdne dane (liczb ujemn lub zero) i ponownie zapyta o dugo promienia.
Zadanie 14.5. Napisz program obliczajcy pole powierzchni piercienia koowego o promieniu zewntrznym R i wewntrznym r. Dugoci promieni uytkownik wprowadza z klawiatury. Program powinien zasygnalizowa bdne dane i ponownie zapyta o potrzebn warto.
Zadanie 14.6. Napisz program wywietlajcy w konsoli cig liczb Fibonacciego mniejszych od 1000. Cig liczb Fibonacciego okrelamy w nastpujcy sposób: F(1) = 1, F(2) = 1, F(n) = F(n–1)+F(n–2) dla n =3, 4, 5…. Pomimo rekurencyjnego charakteru wzoru moemy zrealizowa obliczenia w sposób iteracyjny, uywajc trzech zmiennych i odpowiednio przestawiajc w nich wartoci trzech kolejnych liczb cigu Fibonacciego.
Zadanie 14.7. Napisz program obliczajcy, ile jest liczb w cigu Fibonacciego mniejszych od podanej przez uytkownika liczby cakowitej n.
Zadanie 14.8. Napisz program obliczajcy pole powierzchni trójkta równobocznego i umoliwiajcy wielokrotne powtarzanie oblicze. Jako znak zakoczenia oblicze przyjmij podanie dugoci boku równej 0. Dla wartoci ujemnych wywietl stosowny komunikat i ponów pytanie o dugo boku.
Zadanie 14.9. Napisz program umoliwiajcy wielokrotne wykonywanie oblicze (np. dugoci okrgu). Po wykonaniu oblicze program powinien wywietli pytanie Czy obliczamy dalej (t/n)?. W pytaniu zawarta jest sugestia sposobu udzielenia odpowiedzi: t — tak, n — nie (inne odpowiedzi powinny by ignorowane).
15. Instrukcja ptli typu while Ptla ze sprawdzaniem warunku na pocztku ma posta: while(warunek) instrukcja;
Rozdzia 2. i Drugi krok — operacje wejcia-wyjcia i instrukcje sterujce w Javie
43
Najpierw obliczana jest warto wyraenia logicznego warunek. Jeeli warunek ma warto true, to wykonywana jest instrukcja i nastpuje powrót do badania warunku (cykl si powtarza). Jeeli warunek przyjmie warto false, to dziaanie ptli zostanie zakoczone. Cech charakterystyczn tej ptli jest to, e instrukcja moe nie wykona si ani razu (while(false) instrukcja;). Naley zwróci uwag, aby instrukcja miaa wpyw na badany warunek, gdy moemy uzyska ptl nieskoczon (while(true) instrukcja;). Poniewa skadnia ptli dopuszcza uycie instrukcji pustej, powstaje moliwo przypadkowego utworzenia ptli nieskoczonej w postaci while(true); instrukcja; (wstawienie znaku rednika pomidzy warunek i instrukcj).
Zadanie 15.1. Uytkownik wprowadza z klawiatury dwie liczby naturalne. Nie korzystajc z operatora dodawania (+), oblicz sum tych liczb. Napisz program obliczajcy sum tych liczb, majc do dyspozycji operatory inkrementacji (++) i dekrementacji (––). Wyobra sobie dwa stosy patyczków. Dodawanie realizujesz, przekadajc po jednym patyczku z jednego stosu na drugi. Wykorzystaj ten pomys do rozwizania zadania.
Zadanie 15.2. Uytkownik wprowadza z klawiatury dwie liczby cakowite. Napisz program obliczajcy sum tych liczb, korzystajc z operatorów inkrementacji (++) i dekrementacji (––).
Zadanie 15.3. Napisz program obliczajcy iloczyn liczb cakowitych, nie korzystajc z operatora *. Do dyspozycji masz operatory + i ––. Zadanie rozwi: a) dla pary liczb cakowitych dodatnich, b) dla pary dowolnych liczb cakowitych. W zadaniu b rozwa wszystkie moliwe przypadki i sprowad je ewentualnie do przypadku z zadania a.
Zadanie 15.4. Korzystajc z operatora odejmowania (–), napisz program obliczajcy iloraz cakowity pary liczb cakowitych.
Zadanie 15.5. Korzystajc z operatora odejmowania (–), napisz program obliczajcy reszt z dzielenia pary liczb cakowitych.
44
Programowanie w jzyku Java
Zadanie 15.6. Napisz program obliczajcy cakowity pierwiastek kwadratowy z podanej liczby naturalnej. Nie korzystaj przy tym z funkcji bibliotecznych oraz innych metod przyblionego obliczania pierwiastka kwadratowego i zaokrglenia otrzymanego wyniku zmiennoprzecinkowego do liczby cakowitej. Cakowity pierwiastek kwadratowy z liczby n jest najwiksz liczb naturaln p spe2 niajc nierówno p d n .
Zadanie 15.7. Napisz program wyznaczajcy najmniejsz wspóln wielokrotno (NWW) dla pary liczb cakowitych dodatnich. Obliczaj wielokrotnoci jednej liczby i sprawdzaj, czy obliczona wielokrotno jest wielokrotnoci drugiej liczby (czy dzieli si bez reszty przez drug liczb).
Zadanie 15.8. Korzystajc z algorytmu Euklidesa, napisz program wyznaczajcy najwikszy wspólny dzielnik (NWD) pary liczb cakowitych dodatnich.
Zadanie 15.9. Mamy dwie róne liczby cakowite dodatnie. Bierzemy mniejsz z nich i obliczamy jej wielokrotno do chwili, gdy wielokrotno osignie lub przekroczy warto drugiej liczby. W przypadku równoci mamy ju gotowy wynik. Jeli jednak wielokrotno pierwszej liczby przekroczya warto drugiej liczby, to zaczynamy liczy wielokrotnoci drugiej liczby i porównywa wyniki z obliczon wielokrotnoci pierwszej liczby. Naprzemienne liczenie kolejnych wielokrotnoci zakoczymy w chwili, gdy obie wielokrotnoci bd równe. Uzasadnij, e to postpowanie si zakoczy. Napisz na tej podstawie program wyznaczajcy najmniejsz wspóln wielokrotno (NWW) pary liczb cakowitych dodatnich.
16. Instrukcja ptli typu for Instrukcja ptli typu for ma skadni: for(instrukcja inicjujca; wyraenie logiczne; instrukcja modyfikujca) instrukcja;
Na pocztku wykonywana jest (tylko raz) instrukcja inicjujca. Nastpnie obliczana jest warto wyraenia logicznego (wyraenie logiczne). Jeeli wyraenie logiczne ma warto true, to wykonywana jest instrukcja, w przeciwnym razie (gdy wyraenie logiczne ma warto false) ptla zostaje zakoczona. Po wykonaniu instrukcji
Rozdzia 2. i Drugi krok — operacje wejcia-wyjcia i instrukcje sterujce w Javie
45
(instrukcja) wykonywana jest instrukcja modyfikujca i nastpuje powrót do obliczania wartoci wyraenia logicznego (cykl jest kontynuowany). Instrukcja for czsto przyjmuje posta (n jest ustalon liczb naturaln): for(int i = 0; i < n; ++i) instrukcja; // odliczanie w gór
lub: for(int i = n; i > 0;
i) instrukcja; // odliczanie w dó
W obu przypadkach instrukcja zostanie wykonana n razy, przy czym w pierwszym przypadku zmienna i (zwana czsto zmienn sterujc lub licznikiem) przyjmie kolejno wartoci 0, 1, 2 … n-1, a w drugim przypadku n, n–1, … 1. W kadym cyklu instrukcja modyfikujca zmienia warto zmiennej i (++i — inkrementacja, czyli zwikszenie wartoci zmiennej i o 1, lub ––i — dekrementacja, czyli zmniejszenie zmiennej i o 1). Ptla for nie ogranicza si do przedstawionych wyej zastosowa. W uzasadnionych sytuacjach mona poszczególne instrukcje pomija. W skrajnym przypadku uzyskamy nieskoczon ptl w postaci for(;;);, wykonujc instrukcj pust.
Zadanie 16.1. Napisz program, który nie wykonujc mnoenia, obliczy kwadrat liczby naturalnej. Wykorzystaj fakt, e suma kolejnych liczb nieparzystych jest kwadratem liczby naturalnej: 1 12 , 1 3
4
22 , 1 3 5 9
32 itd.
Zadanie 16.2. Napisz program, który sprawdzi, czy wprowadzone z klawiatury sowo jest palindromem, czyli brzmi tak samo czytane od strony lewej do prawej i od prawej do lewej. Przykadem palindromu jest sowo kajak lub imi Anna (bez rozróniania wielkoci liter). Moesz porównywa podany tekst z tekstem zapisanym tymi samymi znakami w odwrotnej kolejnoci lub porównywa pierwszy znak z ostatnim, drugi z przedostatnim itd.
Zadanie 16.3. Napisz program, który sprawdzi, czy wprowadzone z klawiatury zdanie jest palindromem, czyli brzmi tak samo czytane od strony lewej do prawej i od prawej do lewej. Przykadem zdania-palindromu jest Kobya ma may bok (bez rozróniania wielkoci liter i uwzgldniania odstpów midzy sowami).
Zadanie 16.4. Napisz program wywietlajcy na ekranie tabliczk mnoenia.
46
Programowanie w jzyku Java
Zadanie 16.5. Napisz program wywietlajcy na ekranie tabliczk dodawania i tabliczk mnoenia w pitkowym ukadzie pozycyjnym.
Zadanie 16.6. Napisz program obliczajcy sum n pocztkowych wyrazów cigu harmonicznego. Liczb n uytkownik wprowadza z klawiatury.
Zadanie 16.7. Napisz program obliczajcy silni liczby naturalnej n. Liczb n uytkownik wprowadza z klawiatury.
Zadanie 16.8. Napisz program umoliwiajcy wielokrotne obliczanie potg o wykadniku naturalnym n i podstawie rzeczywistej a. Nie korzystaj z funkcji klasy Math. Podanie wykadnika –1 powinno przerwa dziaanie programu.
Rozdzia 3.
Trzeci krok — budujemy wasne metody i klasy 17. Obsuga wyjtków Wyjtek (ang. exception) — nietypowa sytuacja pojawiajca si podczas dziaania programu. Kady wyjtek w Javie jest obiektem okrelonego typu, przekazywanym do metody, której dziaanie doprowadzio do pojawienia si bdu. Metoda moe przechwyci wyjtek i wykona instrukcje zapobiegajce przerwaniu dziaania programu. Konstrukcja obsugi wyjtków przedstawia si nastpujco: try { instrukcja } catch (typ wyjtku 1 e) { instrukcja obsugi wyjtku 1 } catch (typ wyjtku 2 e) { instrukcja obsugi wyjtku 2 } ... catch (typ wyjtku n e) { instrukcja obsugi wyjtku n } [finally { instrukcja }]
Opcjonalny blok finally jest zawsze wykonywany przed powrotem do instrukcji wystpujcej za konstrukcj try-catch. W kodzie programu moemy generowa wyjtki, stosujc instrukcj throw.
Zadanie 17.1. Podczas wprowadzania danych liczbowych uytkownik moe wiadomie lub przez pomyk wprowadzi cig znaków niebdcy poprawnie zapisan liczb. Spowoduje to przerwanie pracy programu. Napisz program umoliwiajcy wczytywanie z klawiatury liczby zmiennoprzecinkowej typu double przy uyciu metody nextDouble() z klasy Scanner i reagujcy poprawnie na popeniony bd. Naley przechwyci i obsuy wyjtek InputMismatchException (pakiet java.util), a nastpnie ponowi proces wczytywania liczby.
48
Programowanie w jzyku Java
Zadanie 17.2. Dane liczbowe ze standardowego wejcia moemy wczytywa w postaci acucha znaków, a nastpnie konwertowa je na liczby odpowiedniego typu. Napisz program, który w ten sposób wczyta z klawiatury liczb zmiennoprzecinkow i zareaguje poprawnie na popenione bdy. Podczas konwersji acucha na liczb moe wystpi wyjtek NumberFormatException. Naley przechwyci i obsuy ten wyjtek, a nastpnie ponowi proces wczytywania danych.
Zadanie 17.3. Napisz program, który odczyta i obliczy sum piciu liczb cakowitych, wprowadzonych ze standardowego wejcia. Pomi liczby zmiennoprzecinkowe i acuchy znaków niebdce liczbami. Wykorzystaj wyjtki lub informacj, e klasa Scanner oferuje metody sprawdzajce, jaki kolejny token znajduje si w strumieniu. Na przykad metoda hasNextInt() sprawdza, czy kolejny token jest liczb cakowit typu int.
Zadanie 17.4. Napisz program obliczajcy odwrotno liczby cakowitej wprowadzonej z klawiatury. a) Przechwy i obsu wszystkie wyjtki, jakie mog pojawi si podczas
wczytywania danych i wykonywania oblicze. b) Zrealizuj zadanie bez obsugi wyjtków.
Zadanie 17.5. Napisz program obliczajcy wynik dzielenia z reszt dwóch liczb cakowitych wprowadzonych z klawiatury. Przechwy i obsu wyjtki, jakie mog pojawi si podczas wczytywania danych i wykonywania oblicze.
18. Liczby pseudolosowe i tablice jednowymiarowe — budujemy metody statyczne Liczby losowe powstaj w wyniku dziaania mechanizmu losujcego (rzut kostk do gry, losowanie ponumerowanych kul z urny itp.) — rozkad tych liczb jest nieregularny i trudny do przewidzenia. Otrzymywanie liczb losowych w programach komputerowych jest bardzo skomplikowane, wic czsto zastpuje si je liczbami pseudoloso-
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
49
wymi (rozkad tych liczb ma pewne regularnoci, które w wielu zastosowaniach moemy pomin). Do generowania liczb pseudolosowych moemy stosowa statyczn metod java.lang. Math.random(), zwracajc liczb typu double z przedziau 0, 1 , lub obiekt klasy java. util.Random i jedn z dostpnych w klasie metod.
Tablica jednowymiarowa — struktura danych do przechowywania okrelonej liczby danych jednego typu. Ogólna definicja tablicy przedstawia si nastpujco: typ danych [] nazwa tablicy = new typ danych[rozmiar tablicy];
natomiast tablica zainicjowana podanymi wartociami to: typ danych [] nazwa tablicy = { warto 1, warto 2, ..., warto n };
W Javie tablica jest obiektem. Rozmiar tablicy zapisany jest w polu length. Indeksowanie elementów tablicy rozpoczyna si od 0. Jeli podamy indeks spoza zakresu (0..rozmiar tablicy-1), to zostanie wygenerowany wyjtek java.lang.ArrayIndexOutOfBoundsException. Metody statyczne, dostpne w klasie java.util.Arrays pozwalaj na wykonywanie podstawowych operacji na tablicy — sortowanie, wyszukiwanie binarne, kopiowanie itp.
Zadanie 18.1. Napisz program, który przeprowadzi symulacj 100 rzutów kostk i wywietli wyniki w konsoli.
Zadanie 18.2. Napisz program, który przeprowadzi symulacj 1000 rzutów kostk i sporzdzi zestawienie wyników. Nie zapamituj wyników kolejnych rzutów — wystarczy, e bdziesz na bieco zlicza, ile razy wypad dany wynik. Rol licznika moe odgrywa tablica.
Zadanie 18.3. Dwukrotnie rzucamy kostk do gry i zapisujemy sum wyrzuconych oczek. Napisz program, który przeprowadzi symulacj 3000 powtórze dowiadczenia i sporzdzi zestawienie wyników.
Zadanie 18.4. Utwórz funkcj rand() z dwoma parametrami a i b, losujc liczb rzeczywist nalec do przedziau a, b , gdzie a i b s liczbami cakowitymi i a < b. Wynik losowania powinien by podany z precyzj do 0,1. Napisz program demonstrujcy dziaanie tej funkcji.
50
Programowanie w jzyku Java
Zadanie 18.5. Napisz program losujcy 500 liczb rzeczywistych z przedziau 0, 5 . Przedstaw rozkad wylosowanych liczb w przedziaach o dugoci 1.
Zadanie 18.6. Utwórz funkcj (metod statyczn) lotto() losujc 6 rónych liczb z 49 i zwracajc wynik w postaci tablicy liczb cakowitych. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 18.7. Utwórz funkcj (metod statyczn) lotto() z dwoma parametrami m i n, losujc m rónych liczb sporód liczb od 1 do n i zwracajc wynik w postaci tablicy liczb cakowitych. Napisz program demonstrujcy dziaanie tej metody. Rozwizujc kolejne zadania (18.8 – 18.18), zbudujemy klas MyRandomArray, gromadzc metody umoliwiajce tworzenie jednowymiarowych tablic wypenionych pseudolosowymi liczbami typu cakowitego int lub zmiennoprzecinkowego double.
Zadanie 18.8. Utwórz statyczn metod int[] rndArray(int n, int m) suc do budowania tablicy liczb cakowitych o podanym wymiarze n, wypenionej pseudolosowymi wartociami z zakresu 0, 1, …, m-1. Zdefiniuj metody uatwiajce wywietlanie elementów tablicy oddzielonych odstpem void arrayPrint(int[] tab) i void arrayPrintln(int[] tab) — nazwy sugeruj rónic w dziaaniu tych metod. Utwórz równie metod dodajc do wszystkich elementów tablicy okrelon warto void addToArray(int[] tab, int d). Napisz program demonstrujcy dziaanie tych metod. Tworzone metody skopiuj do pliku MyRandomArray.java w biecym folderze. import java.util.Random; public class MyRandomArray { /* Tu skopiuj kody metod */ }
Bdziesz móg z nich korzysta podczas rozwizywania innych zada, np. kod: int[] los = MyRandomArray.rndArray(6, 49); MyRandomArray.addToArray(los, 1); MyRandomArray.arrayPrintln(los);
stanowi przykad losowania 6 liczb z 49 (podobnie jak w rozwizaniu zadania 18.6 — w tym przypadku jednak liczby mog si powtarza ) przy uyciu metod statycznych z klasy MyRandomArray.
Zadanie 18.9. Utwórz statyczn metod int[] rndUniqueArray(int n, int m) suc do budowania tablicy liczb cakowitych o podanym wymiarze (n) i niepowtarzajcych si elemen-
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
51
tach, wypenionej pseudolosowymi wartociami z okrelonego zakresu 0, 1, …, m-1. Napisz program demonstrujcy dziaanie tej metody. Docz j do klasy MyRandomArray. Skorzystaj z rozwizania zadania 18.6.
Zadanie 18.10. Utwórz statyczne metody int[] rndSortArray(int n, int m) i int[] rndSortUniqueArray(int n, int m), które bd suy do budowania posortowanych tablic liczb cakowitych o podanym wymiarze (n), wypenionych pseudolosowymi wartociami z zakresu 0, 1, …, m-1. Druga metoda powinna zwraca tablic o niepowtarzajcych si elementach. Napisz program demonstrujcy dziaanie tych metod. Docz je do klasy MyRandomArray. Skorzystaj z rozwizania zadania 18.9 oraz metody sortujcej z klasy Arrays.
Zadanie 18.11. Utwórz statyczn metod double[] rndArray(int n, double a), która bdzie suy do budowania tablicy liczb zmiennoprzecinkowych typu double o podanym wymiarze (n), wypenionej pseudolosowymi wartociami z przedziau 0, a . Zdefiniuj metody uatwiajce wywietlanie elementów tablicy oddzielonych odstpem void arrayPrint(double[] tab), void arrayPrintln(double[] tab) i void arrayPrintf(String spec, double[] tab) — nazwy sugeruj sposób dziaania tych metod. Ponadto utwórz metod dodajc do wszystkich elementów tablicy okrelon warto void addToArray(double[] tab, double d). Napisz program demonstrujcy dziaanie tych metod. Skorzystaj z rozwizania zadania 18.8.
Metody te maj nazwy takie same jak metody istniejce w klasie MyRandomArray, ale róni si typami parametrów wywoania. Moemy wic te metody dodawa do klasy MyRandomArray — wykorzystujemy tutaj moliwo przeciania metod.
Zadanie 18.12. Utwórz statyczn metod double[] rndUniqueArray(int n, double a), która bdzie suy do budowania tablicy liczb zmiennoprzecinkowych o podanym wymiarze (n) i niepowtarzajcych si elementach, wypenionej pseudolosowymi wartociami z przedziau 0, a . Napisz program demonstrujcy dziaanie tej metody. Docz j do klasy MyRandomArray. Skorzystaj z rozwizania zadania 18.9.
52
Programowanie w jzyku Java
Zadanie 18.13. Utwórz statyczne metody double[] rndSortArray(int n, double a) i double[] rndSortUniqueArray(int n, double a), które bd suy do budowania posortowanych tablic liczb zmiennoprzecinkowych o podanym wymiarze (n), wypenionych pseudolosowymi wartociami z przedziau 0, a . Druga metoda powinna zwraca tablic o niepowtarzajcych si elementach. Napisz program demonstrujcy dziaanie tych metod. Docz je do klasy MyRandomArray. Skorzystaj z rozwizania zadania 18.10.
Zadanie 18.14. Utwórz statyczn metod void roundArray(double[] tab, int prec), która bdzie zaokrgla wszystkie liczby w tablicy tab do okrelonej liczby miejsc po przecinku (parametr prec). Napisz program demonstrujcy dziaanie tej metody. Docz j do klasy MyRandomArray.
Zadanie 18.15. Utwórz statyczn metod double[] rndArray(int n, double a, int prec), która bdzie suy do budowania tablicy liczb zmiennoprzecinkowych o podanym rozmiarze (n) i wartociach z przedziau 0, a oraz o okrelonej liczbie miejsc po przecinku (parametr prec). Napisz program demonstrujcy dziaanie tej metody. Docz j do klasy MyRandomArray.
Zadanie 18.16. Utwórz statyczn metod double[] rndArray(int n, double a, double step), która bdzie suy do budowania tablicy liczb zmiennoprzecinkowych o podanym rozmiarze (n) i wartociach z przedziau 0, a bdcych wielokrotnoci parametru step. Napisz program demonstrujcy dziaanie tej metody. Docz j do klasy MyRandomArray.
Zadanie 18.17. Utwórz statyczne metody void inputArray(int[] tab) i void inputArray(double[] tab), które bd umoliwia wprowadzanie danych z klawiatury do tablicy odpowiedniego typu. Napisz program demonstrujcy dziaanie tych metod. Utwórz klas MyArray i umie w niej te dwie metody oraz wczeniej zdefiniowane metody suce do wywietlania zawartoci tablic jednowymiarowych i do zaokrglania wartoci w tablicy liczb typu double (z klasy MyRandomArray).
Zadanie 18.18. Utwórz statyczn metod konwertujc tablic liczb cakowitych na tablic liczb zmiennoprzecinkowych (double[] intArrayToDouble(int[] tab)) oraz metod (int[] doubleArrayToInt(double[] tab)) dziaajc odwrotnie.
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
53
Utwórz drug tablic o takim samym rozmiarze, z odpowiednim typem danych, i przepisz do niej elementy z pierwszej tablicy, stosujc rzutowanie typów.
19. Dokumentacja klasy JDK zawiera narzdzie javadoc, generujce na podstawie komentarzy dokumentacyjnych w plikach ródowych dokumentacj w formie plików HTML. W komentarzach mona umieszcza dowolny tekst, znaczniki jzyka HTML oraz specjalne znaczniki dokumentacyjne (zaczynajce si od znaku @). Komentarz dokumentacyjny zaczyna si od znaku /** i koczy si znakiem */. Komentarze blokowe /* ... */ i liniowe // ... s podczas tworzenia dokumentacji pomijane. W kolejnych zadaniach poznasz wybrane przykady z zakresu tworzenia dokumentacji.
Zadanie 19.1. Przygotuj „cigawk” z instrukcj obsugi aplikacji javadoc.exe dla uywanego rodowiska JDK. W konsoli wykonaj polecenie javadoc –help > opis.txt. W pliku opis.txt znajdziesz wszystkie opcje aplikacji javadoc.exe.
Zadanie 19.2. Utwórz plik ródowy Z19 2.java, który bdzie zawiera nastpujcy kod: public class Z19 2 { private static final String HELLO = "Hello World!"; static String hello() { return HELLO; } public static void main(String args[]) { System.out.println(hello()); } }
Skompiluj i uruchom przykad. Dokumentacj klasy Z19 2 moesz sporzdzi, postpujc wedug schematu: otwórz konsol, przejd do folderu z plikiem Z19 2.java,
54
Programowanie w jzyku Java wykonaj polecenie: javadoc Z19 2.java (zapoznaj si z treci uwagi), otwórz plik index.html i obejrzyj dokumentacj klasy.
Powtórz zadanie, tworzc kilka wersji dokumentacji — zapamitaj znaczenie uytych opcji: a) javadoc –d Z19 2a -nohelp Z19 2.java b) javadoc –d Z19 2b -notree Z19 2.java c) javadoc –d Z19 2c -noindex Z19 2.java d) javadoc –d Z19 2d -nodeprecatedlist Z19 2.java e) javadoc –d Z19 2e –nodeprecatedlist -noindex -notree -nohelp –private Z19 2.java Aby unikn kolizji pomidzy plikami dokumentacji (nadpisywanie plików), przyjmij za zasad tworzenie dokumentacji dla poszczególnych zada w odrbnych folderach. Nazwy folderów niech zawieraj numer zadania. W zwizku z tym ju od tego zadania uywaj opcji –d, wskazujc folder, w którym zostanie zapisana dokumentacja. Zatem zamiast polecenia javadoc Z19 2.java zastosuj polecenie javadoc –d Z19 2 Z19 2.java. Dokumentacja klasy zostanie zapisana w biecym folderze, w podfolderze Z19 2.
Zadanie 19.3. Utwórz plik ródowy Z19 3.java, który bdzie zawiera kod z zadania 19.2. Wstaw komentarze w postaci /** tekst komentarza */ przed kodem klasy, definicj staej i definicjami metod. W komentarzach zawrzyj zwize opisy przedstawianych elementów. Sporzd dokumentacj i przeanalizuj otrzymany dokument. Zastosuj opcje –d i –private.
Zadanie 19.4. Rozwizujc zadania 18.8, 18.11, 18.17 i 18.18, utworzylimy kilka statycznych metod uatwiajcych prac z jednowymiarowymi tablicami liczb cakowitych typu int i tablicami liczb zmiennoprzecinkowych typu double. Metody zostay zgromadzone w klasie MyArray. Na tej podstawie utwórz klas MyIntArray, która bdzie zawiera metody dziaajce na tablicach liczb cakowitych (moesz zmieni nazwy metod lub doda dodatkowe metody), i sporzd dokumentacj tej klasy (dokumentacj zapisz w folderze MyIntArray). W dokumentacji umie informacje o autorze i wersji klasy. W komentarzu do klasy wykorzystaj znaczniki @author i @version. Dokumentacj utwórz z opcjami –author i –version.
Zadanie 19.5. Na podstawie rozwiza zada 18.8, 18.11, 18.17, 18.18 i 19.4 zbuduj klas MyDoubleArray, która bdzie zawiera statyczne metody uatwiajce prac z jednowymiarowy-
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
55
mi tablicami liczb typu double. Sporzd dokumentacj klasy i zapisz j w folderze MyDoubleArray.
Zadanie 19.6. Na podstawie rozwizania zadania 19.5 zbuduj klas MyFloatArray, która bdzie zawiera statyczne metody uatwiajce prac z jednowymiarowymi tablicami liczb typu float. Sporzd dokumentacj klasy i zapisz j w folderze MyFloatArray. Utwórz wspóln dokumentacj klas MyIntArray, MyDoubleArray i MyFloatArray w folderze MyArrays.
Zadanie 19.7. W pliku MyRandomArray.java, utworzonym podczas rozwizywania zada z rozdziau 18., wpisz komentarze dokumentacyjne. Utwórz dokumentacj klasy MyRandomArray i zapisz t dokumentacj w folderze o tej samej nazwie.
20. Dziaania na uamkach — budujemy klas Fraction Rozwizujc systematycznie kolejne zadania, bdziemy tworzy wasn klas Fraction (uamki) oraz programy ukazujce moliwoci tej klasy. Na bieco zbudujemy dokumentacj klasy.
Zadanie 20.1. Zbuduj klas Fraction, która bdzie zawiera dwa prywatne pola reprezentujce licznik i mianownik uamka. W klasie tej umie konstruktor z dwoma parametrami, który bdzie budowa uamek na podstawie dwóch liczb cakowitych (licznika i mianownika), oraz publiczn metod toString(), zwracajc uamek w postaci acucha znaków, np. "4/13" (licznik, kreska uamkowa / i mianownik). Napisz program pokazujcy dziaanie konstruktora i zdefiniowanej metody.
Zadanie 20.2. Dodaj do klasy Fraction konstruktor bezparametrowy budujcy uamek odpowiadajcy liczbie 0 oraz konstruktor z jednym parametrem cakowitym m budujcy uamek m/1. Napisz program pokazujcy dziaanie tych konstruktorów.
Zadanie 20.3. Utwórz w klasie Fraction konstruktor kopiujcy i napisz program pokazujcy dziaanie tego konstruktora.
56
Programowanie w jzyku Java
Zadanie 20.4. Zauwamy, e obiekty new Fraction(-3, 4) i new Fraction(3, -4) reprezentuj ten 3 4
sam uamek . Po zamianie obiektów na acuchy znaków (metod toString()) otrzymamy odpowiednio "-3/4" i "3/-4". Podobnie wygldaaby sytuacja dla obiektów new Fraction(2, 5) i new Fraction(-2, -5) reprezentujcych uamek 2/5. Zapis uamka w postaci "3/-4" lub "-2/-5" nie wyglda korzystnie (lepszy bdzie zapis "-3/4" lub "2/5"). Mona przyj, e bdziemy zapamitywali zawsze dodatni mianownik, a znak licznika zadecyduje o znaku uamka. Dodaj do klasy Fraction prywatn metod, która wywoana wewntrz konstruktora skoryguje licznik i mianownik uamka zgodnie z przyjt umow. Napisz program pokazujcy skutki dziaania tej metody. Metod nazwij correction() (poprawka). Bdzie ona przydatna podczas wyznaczania odwrotnoci ujemnego uamka lub dzielenia przez taki uamek.
Zadanie 20.5. Zauwamy, e obiekty new Fraction(3, 4) i new Fraction(15, 20) reprezentuj ten sam uamek 3/4. Dodaj do klasy Fraction publiczne metody suce do skracania uamka (przez najwikszy wspólny dzielnik licznika i mianownika lub inn podan warto) oraz publiczn metod pozwalajc na rozszerzanie uamka. Napisz program pokazujcy dziaanie tych metod. Metod skracajc uamek nazwij reduce() (ang. reducing fraction — skraca uamek). Do realizacji tej metody niezbdna bdzie prywatna metoda obliczajca najmniejszy wspólny dzielnik (ang. Greatest Common Factor — GCF). Proponujemy w tym przypadku uycie polskiego skrótu nwd. Metod rozszerzajc uamek nazwij equivalent() (ang. equivalent fraction — uamek).
Zadanie 20.6. W klasie Fraction utwórz metody zwracajce nowy obiekt Fraction, bdcy iloczynem uamka reprezentowanego przez ten obiekt i inny obiekt lub liczb cakowit. Napisz program pokazujcy dziaanie tych metod. Dziki moliwoci przeciania nazw metod obie metody mog mie t sam nazw mult() (ang. multiplication — mnoenie).
Zadanie 20.7. W klasie Fraction utwórz metody statyczne (o nazwie product(), ang. product — iloczyn) zwracajce obiekt Fraction, bdcy iloczynem dwóch uamków, uamka i liczby cakowitej lub dwóch liczb cakowitych. Napisz program demonstrujcy dziaanie tych metod.
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
57
Zadanie 20.8. W klasie Fraction utwórz metod zwracajc nowy obiekt Fraction, reprezentujcy uamek odwrotny do uamka zawartego w obiekcie wywoujcym t metod. Utwórz metod statyczn o podobnej funkcjonalnoci. Napisz program pokazujcy dziaanie tych metod. Wykorzystaj odwrotno do obliczenia ilorazu dwóch uamków. Metodom nadaj nazw multInv(), pochodzc od okrelenia ang. multiplicative inverse — odwrotno (liczby).
Zadanie 20.9. W klasie Fraction utwórz metody zwracajce nowy obiekt Fraction, bdcy ilorazem uamka reprezentowanego przez ten obiekt i inny obiekt lub liczb cakowit. Metodom nadaj nazw div() (ang. division — dzielenie).
Zadanie 20.10. W klasie Fraction utwórz metody statyczne (o nazwie quot(), ang. quotient — iloraz) zwracajce obiekt Fraction, bdcy ilorazem dwóch uamków, uamka i liczby cakowitej lub dwóch liczb cakowitych. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 20.11. W klasie Fraction utwórz metody (o nazwie add(), ang. addition — dodawanie) zwracajce nowy obiekt Fraction, bdcy sum uamka reprezentowanego przez ten obiekt i inny obiekt lub liczb cakowit. Napisz program pokazujcy dziaanie tych metod. Podczas dodawania uamków o rónych mianownikach niezbdne jest sprowadzenie uamków do wspólnego mianownika. Wspólnym mianownikiem moe by iloczyn mianowników, czyli dodawanie moemy wykona wedug wzoru
a c b d
ad bc bd bd
ad bc . Korzystniej bdzie jednak bd
obliczy najmniejsz wspóln wielokrotno (NWW(b, d)) mianowników i t liczb przyj jako wspólny mianownik (zob. rozwizania zada 15.7 lub 15.9). Prywatn metod nww() dodaj do klasy Fraction.
Zadanie 20.12. W klasie Fraction utwórz metody statyczne (o nazwie sum(), ang. sum — suma) zwracajce obiekt Fraction, bdcy sum dwóch uamków lub uamka i liczby cakowitej. Napisz program demonstrujcy dziaanie tych metod.
58
Programowanie w jzyku Java
Zadanie 20.13. W klasie Fraction utwórz metod zwracajc nowy obiekt Fraction, reprezentujcy uamek przeciwny do uamka zawartego w obiekcie wywoujcym t metod. Utwórz metod statyczn o podobnej funkcjonalnoci. Napisz program pokazujcy dziaanie tych metod. Wykorzystaj uamek przeciwny do obliczenia rónicy dwóch uamków. Metodom nadaj nazw addInv(), pochodzc od okrelenia ang. additive inverse — liczba przeciwna.
Zadanie 20.14. W klasie Fraction utwórz metody (o nazwie sub(), ang. subtraction — odejmowanie) zwracajce nowy obiekt Fraction, bdcy rónic uamka reprezentowanego przez ten obiekt i inny obiekt lub liczb cakowit. Napisz program pokazujcy dziaanie tych metod.
Odejmowanie moemy wykona wedug wzoru
a c b d
ad bc bd bd
ad bc lub bd
stosujc jako wspólny mianownik NWW(b, d). Proponujemy uproci spraw i zastpi odejmowanie dodawaniem liczby przeciwnej:
a c b d
a c . b d
Zadanie 20.15. W klasie Fraction utwórz metody statyczne (o nazwie diff(), ang. difference — rónica) zwracajce obiekt Fraction, bdcy rónic dwóch uamków lub uamka i liczby cakowitej. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 20.16. Dodaj do klasy Fraction metody (getNum() i getDen()) pozwalajce na odczytanie wartoci prywatnych pól obiektu (licznika i mianownika uamka reprezentowanego przez obiekt). Napisz program demonstrujcy dziaanie tych metod.
Zadanie 20.17. Dopuszcza si zmiany wartoci prywatnych pól obiektu (przy uyciu metod) w celu zmiany jego wartoci bez tworzenia nowej instancji obiektu. Zdefiniuj w klasie Fraction metody setNum(int), setDen(int) i setFrac(int, int), które bd zmienia warto licznika, mianownika lub jednoczenie licznika i mianownika uamka (obiektu). Napisz program demonstrujcy dziaanie tych metod.
Zadanie 20.18. Metoda Object.equals() jest dziedziczona przez wszystkie klasy i pozwala ustali, czy dwa obiekty s identyczne. W klasie Fraction za równe uznamy te obiekty, które reprezentuj ten sam uamek. Utwórz i docz do klasy metod equals(), przesania-
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
59
jc metod Object.equals(), oraz napisz program testujcy poprawno dziaania zbudowanej metody.
Do porównania uamków wykorzystaj zaleno
a b
c ad d
bc . Metoda ta
zawiedzie, gdy warto iloczynów (ad lub bc) przekroczy zakres liczb cakowitych. Bezpieczniejszym rozwizaniem byoby doprowadzenie obu uamków do postaci nieskracalnej — takie uamki bd równe wtedy i tylko wtedy, gdy bd miay równe liczniki i równe mianowniki, np.
12 27
4 20 i 9 45
4 12 , wic 9 27
20 . 45
Metoda equals() powinna by zwrotna, symetryczna i przechodnia (cechy relacji równowanoci). Ponadto powinna by spójna, czyli wielokrotne wywoywanie x.equals(y) musi konsekwentnie zwraca t sam warto (albo true, albo false), o ile nie zostaa zmodyfikowana adna dana wykorzystywana do porównywania (w naszym przypadku skracanie lub rozszerzanie uamka nie moe mie wpywu na wynik porównania). Jeli x jest niepust referencj (wskazuje obiekt), to x.equals (null) musi zwraca warto false. Jeli w klasie przedefiniujemy metod equals(), to naley równie przedefiniowa metod hashCode(). Jest to konieczne do prawidowej wspópracy klasy z kolekcjami korzystajcymi z kodowania mieszajcego (np. HashSet).
Zadanie 20.19. Dodaj do klasy Fraction metody zwracajce warto dziesitn uamka reprezentowanego przez obiekt. Napisz program demonstrujcy dziaanie tych metod. Podziel licznik przez mianownik, pamitajc o tym, aby co najmniej jedn z liczb rzutowa przed wykonaniem dzielenia na typ zmiennoprzecinkowy. Sugerowane nazwy metod to doubleValue() i floatValue(); dla metod statycznych: toDouble(Fraction), toFloat(Fraction).
Zadanie 20.20. Uamek moe by przedstawiony jako acuch znaków w postaci "4/7" (uamek zwyky), "5" (liczba cakowita odpowiadajca uamkowi 5/1), "2.45" (uamek dziesitny odpowiadajcy uamkowi 245/100) lub "2,45" (wedug zasad zapisu obowizujcych w Polsce). Zbuduj konstruktor, który na podstawie acucha znaków utworzy odpowiedni obiekt klasy Fraction lub zgosi wyjtek, gdy acuch znaków nie bdzie przedstawia uamka. Napisz program demonstrujcy dziaanie tego konstruktora.
Zadanie 20.21. Zbuduj kilka metod statycznych o nazwie valueOf() z jednym parametrem (typu float, double, int, String) lub dwoma parametrami (typu int), zwracajcych obiekt Fraction
60
Programowanie w jzyku Java
reprezentujcy uamek o wartoci odpowiadajcej podanemu parametrowi. Napisz program demonstrujcy dziaanie tych metod. W kolejnych zadaniach (20.22 – 20.27) wykorzystamy obiekty i metody klasy Fraction, uzyskujc wyniki oblicze w postaci dokadnej, wyraonej uamkami zwykymi.
Zadanie 20.22. Okrelamy nieskoczony cig liczbowy w nastpujcy sposób: a1 1 , a2 1 1 , 1
a3
1 , 1 1 a4 1 1
1
1 1
…. Korzystajc z obiektów i metod klasy Fraction, na1
1
1 1
pisz program obliczajcy 15 pocztkowych wyrazów cigu. Ile maksymalnie wyrazów tego cigu mógby w tym programie obliczy?
Zadanie 20.23. Korzystajc z obiektów i metod klasy Fraction, napisz program obliczajcy sumy czciowe nieskoczonego szeregu 1 1 1 1 1 ... . 2
4
8
16
Zadanie 20.24. Korzystajc z obiektów i metod klasy Fraction, napisz program obliczajcy sumy czciowe nieskoczonego szeregu 1 1 1 1 1 ... . 2
4
8
16
Zadanie 20.25. Napisz program rozwizujcy równanie o postaci ax b 0 w zbiorze liczb wymiernych, posugujc si obiektami i metodami klasy Fraction.
Zadanie 20.26. Napisz program rozwizujcy metod wyznaczników ukad dwóch równa liniowych z dwiema niewiadomymi w zbiorze liczb wymiernych. Wykorzystaj obiekty i metody klasy Fraction. Utwórz metod det(), która bdzie oblicza wyznacznik, oraz metod inputFraction() do wprowadzania z klawiatury wartoci obiektów klasy Fraction. Wygodnie jest zbudowa metod inputFraction() z jednym parametrem typu String, bdcym opisem poprzedzajcym wprowadzanie (tzw. znak zachty). Wprowadzenie wartoci obiektu a moe wyglda tak: Fraction a = inputFraction ("a = "); — w konsoli pojawi si napis a = i migajcy kursor; uytkownik wpisuje warto i naciska klawisz Enter. Z konsoli pobierzemy tekst i zamienimy go na obiekt Fraction, stosujc metod valueOf(). Pozwoli to na poprawne zinterpretowanie danych o postaci "2,45", "2.45", "-5" lub "2/3".
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
61
Zadanie 20.27. Pierwiastek drugiego stopnia z liczby nieujemnej a moemy obliczy ze wzoru iteracyjnego x
1§ a· ¨ x ¸ , biorc warto pocztkow x = 1. Korzystajc z obiektów i mex¹ 2©
tod klasy Fraction, napisz program obliczajcy przyblienie liczby zwykego.
5 w postaci uamka
Ten proces iteracyjny jest szybko zbieny i 4 – 5 iteracji wystarczy do wyznaczenia wyniku. Wiksza liczba iteracji nie jest moliwa do wykonania przy uyciu klasy Fraction (zbyt szybko rosncy licznik i mianownik uamka).
21. Klasa opakowujca Angle — miara kta i funkcje trygonometryczne Zadanie 21.1. Utwórz klas Angle zawierajc jedno pole prywatne x typu double przechowujce miar kta podan w radianach. W klasie zbuduj konstruktor z jednym parametrem double (miara kta w radianach) i sze metod zwracajcych wartoci funkcji trygonometrycznych kta reprezentowanego przez obiekt. Napisz program demonstrujcy dziaanie konstruktora i utworzonych metod. Oprócz powszechnie znanych funkcji trygonometrycznych sinus, cosinus tangens 1 ) i cotangens w klasie Angle uwzgldnimy mniej popularne funkcje secans ( sec x cos x 1 ). i cosecans ( csc x sin x
Zadanie 21.2. Docz do klasy Angle publiczne metody (radian() i degree()) zwracajce liczb typu double, miar kta reprezentowanego przez obiekt wyraon w radianach i stopniach. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 21.3. Docz do klasy Angle publiczn metod toString(), która bdzie zwraca acuch znaków (o postaci 45°30'15") przedstawiajcy miar kta reprezentowanego przez obiekt wyraon w stopniach, minutach i sekundach. Napisz program demonstrujcy dziaanie tej metody.
62
Programowanie w jzyku Java
Metoda toString() przesoni metod o tej samej nazwie, dziedziczon z klasy Object. Metod t naley zdefiniowa z adnotacj Override (@Override).
Zadanie 21.4. Docz do klasy Angle trzy konstruktory — z jednym, dwoma lub trzema parametrami typu int — umoliwiajce zbudowanie obiektu reprezentujcego kt o podanej liczbie stopni, stopni i minut lub stopni, minut i sekund. Ogranicz liczb stopni do zakresu od 0° do 360°, a liczb minut i sekund do zakresu od 0 do 60. Napisz program demonstrujcy dziaanie tych konstruktorów.
Zadanie 21.5. Cig znaków o postaci 105°30'15" przedstawia miar kta w stopniach, minutach i sekundach ktowych. Utwórz konstruktor w klasie Angle, który zbuduje obiekt reprezentujcy kt o podanej w ten sposób mierze. Napisz program demonstrujcy dziaanie tego konstruktora.
Zadanie 21.6. Utwórz w klasie Angle sze metod o nazwie setOfXxx, gdzie Xxx oznacza nazw funkcji trygonometrycznej, ustawiajcych miar kta reprezentowanego przez obiekt na podstawie podanej wartoci odpowiedniej funkcji (metody te odpowiadaj funkcjom odwrotnym do funkcji trygonometrycznych). Metody zmieniaj warto obiektu, ale nie zwracaj adnej wartoci. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 21.7. Na paszczy nie z ukadem wspórzdnych czsto potrzebujemy wyznaczy miar kta nachylenia prostej przechodzcej przez pocztek ukadu wspórzdnych i punkt P(x, y) do osi OX. Utwórz w klasie Angle metod o nazwie setOfPoint(), ustawiajc miar tego kta jako warto obiektu. Napisz program demonstrujcy dziaanie metody setOfPoint().
Zadanie 21.8. Utwórz w klasie Angle konstruktor z dwoma parametrami typu double, tworzcy nowy obiekt reprezentujcy miar kta nachylenia prostej przechodzcej przez pocztek ukadu wspórzdnych i punkt P(x, y) do osi OX. Napisz program demonstrujcy dziaanie tego konstruktora.
Zadanie 21.9. Zbuduj w klasie Angle statyczne funkcje o nazwie valueOf(), o rónych parametrach (takich samych jak konstruktory zbudowane w zadaniach 21.1, 21.4, 21.5 i 21.8), zwracajce obiekt klasy Angle odpowiadajcy ktowi o podanych parametrach. Napisz program demonstrujcy dziaanie tych metod.
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
63
Zadanie 21.10. Na miarach któw moemy wykonywa dodawanie i odejmowanie. Dodaj do klasy Angle metody add() (sub()), które bd zwraca nowy obiekt, bdcy sum (rónic) miary kta reprezentowanego przez obiekt wywoujcy metod i miary kta w obiekcie podanym jako parametr. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 21.11. Docz do klasy Angle statyczne metody sum() (diff()), które bd oblicza sum (rónic) dwóch obiektów podanych jako parametry (miar któw reprezentowanych przez te obiekty). Wynik powinien by obiektem klasy Angle. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 21.12. Miary któw mona mnoy (dzieli) przez liczb. Napisz metod mult() (div()), która bdzie zwraca nowy obiekt, reprezentujcy kt o mierze bdcej iloczynem (ilorazem) miary kta reprezentowanego przez obiekt i liczby podanej jako parametr (cakowitej lub zmiennoprzecinkowej). Napisz program demonstrujcy dziaanie tych metod.
Zadanie 21.13. Napisz metod prod() (quot()), która bdzie zwraca obiekt klasy Angle, reprezentujcy kt o mierze bdcej iloczynem (ilorazem) miary kta (obiektu) podanego jako parametr i liczby podanej jako drugi parametr. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 21.14. Docz do klasy Angle statyczne pola przechowujce stae wartoci obiektów reprezentujcych wybrane kty: RIGHT ANGLE (kt prosty), STRAIGHT ANGLE (kt pópeny) i FULL ANGLE (kt peny), RADIAN (1 radian), DEGREE (1 stopie), ARCMINUTE (1 minuta ktowa) i ARCSECOND (1 sekunda ktowa). Napisz program pokazujcy wartoci tych staych. Stae w Javie s waciwie zmiennymi deklarowanymi ze sowem kluczowym final. Wartoci staych w czasie dziaania programu nie moemy zmieni .
Zadanie 21.15. Dodaj do klasy Angle metod compl() (ang. complementary angle — kt dopeniajcy), zwracajc obiekt reprezentujcy dopenienie kta (obiektu) podanego jako parametr, i metod suppl() (ang. supplementary angle — kt przylegy), zwracajc obiekt reprezentujcy miar kta przylegego do kta (obiektu) podanego jako parametr. Napisz program demonstrujcy dziaanie tych metod. Klasa Angle jest ju dostatecznie rozbudowana. W kilku kolejnych zadaniach pokaemy przykady wykorzystania pochodzcych z niej obiektów i metod.
64
Programowanie w jzyku Java
Zadanie 21.16. Utwórz metod inputAngle() z jednym parametrem typu String (przeznaczonym do opisania wprowadzanej wielkoci), zwracajc obiekt Angle reprezentujcy kt o mierze podanej w stopniach. Metoda ta powinna poprawnie interpretowa takie dane: liczba cakowita stopni, liczba rzeczywista (uamek dziesitny) bez podawania symbolu stopnia oraz cig znaków zawierajcych stopnie, minuty i sekundy ktowe z odpowiednimi symbolami jednostek (np. 24°30'15"). Napisz program rozwizujcy nastpujce zadanie: W trójkcie równoramiennym kt przy wierzchoku ma miar D . Oblicz miar kta E przylegego do podstawy tego trójkta. Sprawd obliczenia, dodajc miary wszystkich któw wewntrznych trójkta. Podczas wprowadzania danych symbol stopnia (°) moesz uzyska , wpisujc Alt+0176 (przytrzymaj lewy klawisz Alt i wprowad kod 0176 z klawiatury numerycznej). Symbole minuty i sekundy to apostrof i cudzysów (dostpne bezporednio na klawiaturze). Miary któw speniaj zaleno D 2E 180q .
Zadanie 21.17. Napisz program rozwizujcy zadanie: W trójkcie równoramiennym kt przylegy do podstawy ma miar E . Oblicz miar kta D lecego naprzeciw podstawy tego trójkta. Sprawd obliczenia, dodajc miary wszystkich któw wewntrznych trójkta.
Zadanie 21.18. Napisz program rozwizujcy zadanie: Oblicz miary któw w trójkcie równoramiennym o podstawie a i ramieniu dugoci b. Sprawd obliczenia, dodajc miary wszystkich któw wewntrznych trójkta.
Zadanie 21.19. Napisz program rozwizujcy zadanie: Oblicz miary któw w trójkcie równoramiennym o podstawie a i wysokoci (opuszczonej na podstaw) h. Sprawd obliczenia, dodajc miary wszystkich któw wewntrznych trójkta.
Zadanie 21.20. Napisz program rozwizujcy zadanie: Oblicz miary któw w trójkcie o bokach a, b i c. Sprawd obliczenia, dodajc miary wszystkich któw wewntrznych trójkta.
22. Liczby rzymskie i klasa Roman Zadanie 22.1. Napisz program zamieniajcy liczby naturalne podawane z klawiatury w postaci dziesitnej na liczby zapisane w systemie rzymskim. Warunkiem zakoczenia programu powinno by podanie liczby 0.
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
65
Stosujc symbole I, V, X, L, C, D i M oraz reguy zapisu liczb rzymskich, moemy zapisa liczb naturaln z zakresu od 0 do 3999.
Zadanie 22.2. Napisz program odczytujcy warto dziesitn liczby zapisanej znakami rzymskimi. Dane wprowadzamy z klawiatury. Warunkiem zakoczenia programu powinno by wprowadzenie pustego acucha znaków.
Zadanie 22.3. Utwórz metod statyczn decToRoman(), która bdzie zamienia liczb naturaln z zakresu od 1 do 3999 na liczb w zapisie rzymskim. Napisz program demonstrujcy dziaanie tej metody. Skorzystaj z tablic zbudowanych w rozwizaniu zadania 22.1.
Zadanie 22.4. W procesie kodowania liczb rzymskich stosujemy dwie tablice — tablic z wartociami wybranych liczb rzymskich i tablic z odpowiadajcymi im wartociami dziesitnymi. Utwórz klas RN (ang. roman numbers), która bdzie zawiera dwa pola: pole typu String (symbol rzymski) oraz pole typu int (warto dziesitna tej liczby rzymskiej). Klasa powinna udostpnia jedynie tablic z parami wartoci ("M", 1000), ("CM", 900) itd. Zmodyfikuj metod decToRoman() (z zadania 22.3) tak, aby wykorzystywaa tablic z klasy RN.
Zadanie 22.5. Utwórz metod statyczn romanToDec(), która bdzie zamienia liczb zapisan w systemie rzymskim na liczb dziesitn. Napisz program demonstrujcy dziaanie tej metody. Skorzystaj z rozwiza zada 22.2 i 22.4.
Zadanie 22.6. Utwórz klas Roman, która bdzie mie jedno pole typu int zawierajce liczb naturaln z zakresu od 1 do 3999. W klasie tej zbuduj konstruktory tworzce obiekt na podstawie parametru bdcego liczb cakowit lub acuchem znaków przedstawiajcym liczb w zapisie rzymskim. Docz do klasy inne metody przydatne do pracy z liczbami rzymskimi. Napisz program demonstrujcy moliwoci tej klasy. Skorzystaj z rozwiza zada 22.1 – 22.5 oraz dowiadcze zdobytych podczas tworzenia klasy Angle.
66
Programowanie w jzyku Java
Zadanie 22.7. Korzystajc z klasy Roman, napisz aplikacj sprawdzajc umiejtno odczytywania wartoci liczb rzymskich. Liczba pyta powinna by z góry ustalona, a wartoci liczb powinny by losowane z podanego zakresu. Do losowania liczb mona uy metod z klasy MyRandomArray.
Zadanie 22.8. Korzystajc z klasy Roman, napisz aplikacj sprawdzajc umiejtno zapisywania liczb w systemie rzymskim. Liczba pyta powinna by z góry ustalona, a wartoci liczb powinny by losowane z podanego zakresu.
23. Trójmian kwadratowy i klasa QuadratPoly Zadanie 23.1. Zbuduj klas QuadratPoly (ang. quadratic polynomial — trójmian kwadratowy) umoliwiajc rozwizywanie rónych zada dotyczcych trójmianu kwadratowego ( ax 2 bx c, a z 0 ) o wspóczynnikach cakowitych. W klasie tej utwórz konstruktor z trzema parametrami i metod value() z jednym parametrem, zwracajc warto trójmianu kwadratowego dla podanego argumentu. Napisz program demonstrujcy dziaanie konstruktora i zdefiniowanej metody.
Zadanie 23.2. Dodaj do klasy QuadratPoly pole delta przechowujce warto wyrónika trójmianu kwadratowego ( ' b 2 4ac ) i metod getDelta() zwracajc warto wyrónika trójmianu. Obliczenie wyrónika powinno by zrealizowane w konstruktorze podczas tworzenia nowego obiektu. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 23.3. Utwórz i docz do klasy QuadratPoly metod toString() zwracajc trójmian w postaci tekstowej, np. "2x^2-x+3". Napisz program demonstrujcy dziaanie tej metody. Zwró uwag na sposób przedstawiania wspóczynników –1, 1 i 0 — pomi liczby -1 i 1 przed wyraeniem x^2 lub x, pozostawiajc odpowiedni znak; nie wypisuj wyraenia 0x oraz wyrazu wolnego 0.
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
67
Zadanie 23.4. Utwórz w klasie QuadratPoly metod sgnDelta() zwracajc znak wyrónika trójmianu. Od znaku wyrónika zaley liczba pierwiastków trójmianu. Napisz program informujcy o liczbie rzeczywistych pierwiastków trójmianu kwadratowego. Funkcja sgn (ac. signum — znak) zwraca –1, gdy argument jest ujemny, 1, gdy argument jest dodatni, oraz 0 dla wartoci zero.
Zadanie 23.5. Docz do klasy QuadratPoly metody getX1() i getX2() zwracajce pierwiastki trójmianu kwadratowego reprezentowanego przez obiekt. Jeli trójmian nie ma pierwiastków rzeczywistych, to metody mog zwraca warto NaN. Korzystajc z tych metod, napisz program rozwizujcy równanie kwadratowe o wspóczynnikach cakowitych, wprowadzonych z klawiatury.
Zadanie 23.6. Wykresem trójmianu kwadratowego ax 2 bx c, a z 0 jest parabola. Charakterystycznym punktem paraboli jest jej wierzchoek, czyli punkt o wspórzdnych (p, q), gdzie p b i q ' . Docz do klasy QuadratPoly metody getP() i getQ() zwra2a
4a
cajce wspórzdne wierzchoka paraboli. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 23.7. Docz do klasy QuadratPoly metod isAPositve() zwracajc warto true, gdy a jest dodatnie, i false, gdy a jest ujemne. Napisz program wyznaczajcy zbiór wartoci dla podanego trójmianu kwadratowego. 2 Jeli a > 0, to zbiorem wartoci trójmianu ax bx c jest przedzia q, f , a dla
a < 0 — przedzia f, q .
Zadanie 23.8. Napisz program, który dla danego trójmianu kwadratowego okreli jego warto ekstremaln (minimum lub maksimum). Dane trójmianu uytkownik wprowadzi z klawiatury.
Zadanie 23.9. Docz do klasy QuadratPoly metod getVertex() (ang. vertex — wierzchoek), która bdzie zwraca wspórzdne wierzchoka paraboli bdcej wykresem trójmianu reprezentowanego przez obiekt. Wynik powinien by podany w postaci acucha znaków. Napisz program demonstrujcy dziaanie tej metody.
68
Programowanie w jzyku Java
Zadanie 23.10. Docz do klasy QuadratPoly metod getCodomain() (ang. codomain — przeciwdziedzina funkcji), która bdzie zwraca zbiór wartoci trójmianu (przedzia liczbowy) zapisany w postaci acucha znaków. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 23.11. Napisz program sporzdzajcy opis przebiegu zmiennoci funkcji kwadratowej f ( x ) ax 2 bx c, a z 0 . Opis zredaguj w punktach. Umie w opisie dziedzin funkcji, zbiór wartoci, monotoniczno , ekstremum, miejsca zerowe i krótkie objanienie wykresu.
Zadanie 23.12. Napisz program rozwizujcy nierówno kwadratow ax 2 bx c ! 0, a z 0 .
Zadanie 23.13. Napisz program rozwizujcy nierówno kwadratow ax 2 bx c t 0, a z 0 .
Zadanie 23.14. Docz do klasy QuadratPoly metod mult() z parametrem bdcym liczb cakowit rón od zera, która zwraca nowy obiekt, iloczyn tej liczby i trójmianu reprezentowanego przez obiekt wywoujcy t metod. Napisz program demonstrujcy jej dziaanie.
Zadanie 23.15. Docz do klasy QuadratPoly metod solutionOfQE() (ang. solution — rozwizanie), która bdzie zwraca rozwizanie równania kwadratowego w postaci zbioru pierwiastków (acuch znaków), np. {–2, 0.5}, {–3} lub {} (odpowiednio: dwa róne pierwiastki, pierwiastek dwukrotny lub brak pierwiastków rzeczywistych — zbiór pusty). Napisz program demonstrujcy dziaanie tej metody. W zestawie znaków dla konsoli nie znajdziemy symbolu zbioru pustego (), wic proponujemy zastpienie go pust par nawiasów klamrowych {}.
Zadanie 23.16. Docz do klasy QuadratPoly dwie prywatne metody: solutionQIe1() i solutionQIe2(), które bd zwraca zbiór rozwiza nierównoci kwadratowej ax 2 bx c ! 0, a z 0 (pierwsza metoda) i ax 2 bx c t 0, a z 0 (druga metoda). Wynik powinien by podany w postaci acucha znaków. Korzystajc z tych metod, zbuduj publiczn metod solutionQIe() (ang. quadratic inequality — nierówno kwadratowa) z jednym
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
69
parametrem (typu String) o postaci "=", okrelajcym typ nierównoci. Napisz program demonstrujcy rozwizywanie nierównoci kwadratowych. Wykorzystaj zbudowane metody prywatne i fakt, e nierówno ax bx c 2
( ax bx c d 0 ) 2
jest
równowana
nierównoci
0 ax bx c ! 0 2
( ax bx c t 0 ). 2
Zadanie 23.17. Napisz program rozwizujcy równanie dwukwadratowe o wspóczynnikach cakowitych ( ax 4 bx 2 c 0, a z 0 ).
Zadanie 23.18. Trójmiany kwadratowe mona dodawa lub odejmowa. Wynik nie zawsze jednak bdzie trójmianem kwadratowym. Docz do klasy metody add() i sub(), które bd zwraca nowy obiekt QuadratPoly, odpowiednio sum i rónic obiektu wywoujcego metod i obiektu przekazanego jako parametr.
Zadanie 23.19. Zbuduj klas FloatQP lub DoubleQP (ang. quadratic polynomial — trójmian kwadratowy), która bdzie umoliwia rozwizywanie rónych zada dotyczcych trójmianu kwadratowego ( ax 2 bx c, a z 0 ) o wspóczynnikach zmiennoprzecinkowych (typu float lub double). Jeli wynik nie jest obiektem klasy, to zgo wyjtek. Do klasy dodaj metod div() zwracajc nowy obiekt, wynik dzielenia trójmianu przez liczb rón od zera. Napisz program demonstrujcy dziaanie konstruktora i wybranych metod.
24. Liczby zespolone — budujemy klas Complex Brak rozwizania równania kwadratowego x 2 1 w zbiorze liczb rzeczywistych doprowadzi do odkrycia jednostki urojonej i — takiej, e i 2 1 — oraz liczb urojonych (bdcych iloczynami liczby rzeczywistej i jednostki urojonej — ai). W konsekwencji doprowadzio to do powstania teorii liczb zespolonych. Liczb zespolon moemy zapisywa w postaci pary liczb rzeczywistych (a, b), gdzie a oznacza cz rzeczywist liczby zespolonej, b — cz urojon. T par liczb moemy interpretowa jako wspórzdne punktu na paszczy nie (tzw. paszczyzna zespolona). Inn moliwoci jest zapis a+bi, czyli posta kanoniczna liczby zespolonej.
70
Programowanie w jzyku Java
Zadanie 24.1. Zbuduj klas Complex, której obiekty bd reprezentoway liczby zespolone. Klasa powinna posiada dwa prywatne pola typu double, co najmniej jeden konstruktor z dwoma parametrami (typu double), metody ustawiajce warto czci rzeczywistej i urojonej oraz moliwo przedstawienia liczby w postaci algebraicznej (kanonicznej). Napisz aplikacj pokazujc dziaanie konstruktorów metod tej klasy. Prywatne pola klasy Complex oznaczmy identyfikatorami re (ang. real — cz rzeczywista liczby zespolonej) i im (ang. imaginary — cz urojona). Metody setRe (double x) i setIm(double y) powinny umoliwi zmian wartoci liczby zespolonej reprezentowanej przez obiekt, natomiast metoda toString() zwróci acuch znaków reprezentujcy posta kanoniczn liczby.
Zadanie 24.2. Napisz aplikacj rozwizujc równanie kwadratowe o wspóczynnikach rzeczywistych w zbiorze liczb zespolonych. Algorytm rozwizywania równania jest taki sam jak w zbiorze liczb rzeczywistych. Jedynie w przypadku, gdy wyrónik jest ujemny ( ' 0 ), rozwizaniem równania bdzie para liczb zespolonych, poniewa ' 'i .
Zadanie 24.3. Docz do klasy Complex metody zwracajce sum (add() — ang. addition) i rónic (sub() — ang. subtraction) wartoci zespolonej reprezentowanej przez obiekt i wartoci podanej jako parametr. Napisz aplikacj pokazujc dziaanie tych metod.
Zadanie 24.4. Docz do klasy Complex metody zwracajce liczb zespolon przeciwn (opp() — ang. opposite lub additive inverse), sprzon (conj() — ang. conjugate) i odwrotn (rec() — ang. reciprocal lub multiplicative inverse) do wartoci zespolonej reprezentowanej przez obiekt. Napisz aplikacj pokazujc dziaanie tych metod.
Zadanie 24.5. Docz do klasy Complex metody zwracajce iloczyn (mult() — ang. multiplication) i iloraz (div() — ang. division) wartoci zespolonej reprezentowanej przez obiekt i wartoci podanej jako parametr. Napisz aplikacj pokazujc dziaanie tych metod.
Zadanie 24.6. Dodaj do klasy Complex stae ZERO (zero), ONE (jeden), I (jednostka urojona i — ang. imaginary unit). Napisz aplikacj pokazujc znaczenie tych staych.
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
71
Staa ZERO jest elementem neutralnym dla dodawania, a staa ONE stanowi element neutralny dla mnoenia. Korzystajc ze staej I, moemy pokaza potgi jednostki urojonej.
Zadanie 24.7. Docz do klasy Complex metody zwracajce bezwzgldn warto (modu) liczby zespolonej (abs() — ang. absolute value) i argument gówny liczby zespolonej (arg()) reprezentowanej przez obiekt. Napisz aplikacj pokazujc dziaanie tych metod.
Zadanie 24.8. Docz do klasy Complex metody zwracajce cz rzeczywist (getRe()) i cz urojon (getIm()) liczby zespolonej reprezentowanej przez obiekt. Napisz aplikacj pokazujc dziaanie tych metod.
Zadanie 24.9. Dodaj do klasy Complex bezparametrowe metody print() i println() wywietlajce posta kanoniczn liczby zespolonej w konsoli. Zbuduj te metody równie z jednym parametrem typu String. Podany acuch znaków powinien poprzedza wywietlan liczb zespolon. Napisz aplikacj pokazujc dziaanie tych metod. Zaproponowane metody skróc nam zapis wielu rozwiza zada. Rónica w dziaaniu metody println() i print() jest oczywista i w naszej implementacji nie powinna odbiega od przyjtego standardu.
Zadanie 24.10. Docz do klasy Complex konstruktor kopiujcy oraz metod umoliwiajc porównywanie obiektu wywoujcego t metod z innym obiektem podanym jako parametr. Napisz aplikacj pokazujc porównywanie obiektów.
Zadanie 24.11. Docz do klasy Complex konstruktor tworzcy obiekt na podstawie acucha znaków przedstawiajcego liczb zespolon w postaci "–3.4+2.75i". Napisz aplikacj pokazujc dziaanie tego konstruktora. Konstruktor powinien poprawnie przetwarza acuchy o postaci: "1", "–2.5", "+3.5", "i", "+i", "–i", "2+3i", "–2.3+3i", "2–3i", "–2.3+3i", "+2–3.7i", "+2+3.7i", "1+i", "2.1–i". Aby zbytnio nie komplikowa kodu, zrezygnujemy z zapisywania liczb w notacji naukowej.
Zadanie 24.12. Zbuduj w klasie Complex metod statyczn parseComplex() zamieniajc acuch znaków na liczb zespolon. Napisz aplikacj pokazujc dziaanie tej metody.
72
Programowanie w jzyku Java
Zastosuj konstruktor zbudowany w rozwizaniu zadania 24.11.
Zadanie 24.13. Utwórz poza klas Complex funkcj power() obliczajc potg o wykadniku cakowitym dla dowolnej liczby zespolonej. Napisz aplikacj pokazujc dziaanie tej funkcji.
Zadanie 24.14. Dodaj opracowan w zadaniu 24.13 funkcj power() do klasy Complex jako metod statyczn oraz niestatyczn. Napisz aplikacj pokazujc dziaanie metod power(). W metodzie statycznej podstawa potgi przekazywana jest jako parametr wywoania, natomiast w metodzie niestatycznej podstaw potgi stanie si warto obiektu wywoujcego t metod (wykorzystaj sowo kluczowe this).
Zadanie 24.15. Docz do klasy Complex metody obliczajce kwadrat liczby zespolonej (sqr()) i pierwiastek kwadratowy (sqrt()) z liczby zespolonej. Napisz aplikacj pokazujc dziaanie tych metod. W zbiorze liczb zespolonych okrelamy dwa pierwiastki drugiego stopnia. S one liczbami przeciwnymi. Podczas rozwizywania zada naley o tym pamita . Mona utworzy metod nextSqrt(), wyznaczajc drugi pierwiastek z liczby zespolonej, lub poda w metodzie sqrt()parametr, wskazujcy, który z tych pierwiastków chcemy obliczy .
Zadanie 24.16. Docz do klasy Complex metody printf() i printlnf(), które bd wywietla w konsoli liczb zespolon z okrelon precyzj domyln (6 miejsc po przecinku). Napisz program demonstrujcy dziaanie tych metod. Zob. rozwizanie zadania 24.9.
Zadanie 24.17. Napisz program rozwizujcy w zbiorze liczb zespolonych równanie kwadratowe o wspóczynnikach zespolonych, np.: 1 2i z 2 iz 1 0 .
Zadanie 24.18. Docz do klasy Complex cztery metody statyczne (sum(), diff(), prod() i quot()), które bd realizowa cztery podstawowe dziaania (dodawanie, odejmowanie, mnoenie i dzielenie) w zbiorze liczb zespolonych.
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
Liczb zespolon z
x yi moemy przeksztaci na posta z
73
z (sin M i cos M )
nazywan postaci trygonometryczn liczby zespolonej ( z — modu, M — argument liczby z). Posta trygonometryczn liczby zespolonej moemy skojarzy z biegunowym ukadem wspórzdnych — liczb zespolon moemy przedstawia jako par r , M , gdzie r jest (promieniem) odlegoci punktu P(x, y) od pocztku ukadu wspórzdnych, a M jest ktem pomidzy promieniem i osi X ukadu wspórzdnych.
Zadanie 24.19. Utwórz klas PolarComplex, której obiekty bd reprezentoway liczby zespolone podane we wspórzdnych biegunowych (ang. polar coordinates). Zbuduj podstawowe konstruktory klasy PolarComplex, metod zamieniajc obiekt klasy PolarComplex na obiekt Complex i metod toString() zamieniajc obiekt na acuch znaków, np. "[r=1,500000; fi=1,000000]". Napisz program demonstrujcy dziaanie tych konstruktorów i metod. Podany cig znaków "[r=1,500000; fi=1,000000]" jest propozycj, z któr Czytelnik niekoniecznie musi si zgadza . Nie ma w tym przypadku standardu zapisu liczb podobnego do postaci kanonicznej liczby zespolonej i atwego do zapisania w postaci acucha znaków. Posta trygonometryczna liczby zespolonej z r sin M i cos M i posta wykadnicza z re iM wykorzystuj elementy pary r , M , ale do tego celu niezbyt si nadaj. Pozostamy zatem przy zaproponowanej w zadaniu postaci acucha.
Zadanie 24.20. Docz do klasy PolarComplex konstruktor kopiujcy i konstruktor z parametrem typu Complex. Napisz program demonstrujcy dziaanie tych konstruktorów.
Zadanie 24.21. Docz do klasy Complex konstruktor z parametrem typu PolarComplex i metod toPolarComplex(), która bdzie zwraca obiekt klasy PolarComplex odpowiadajcy obiektowi Complex. Napisz program demonstrujcy dziaanie tego konstruktora i tej metody.
Zadanie 24.22. Docz do klasy PolarComplex metod mult(), która bdzie zwraca iloczyn liczby zespolonej reprezentowanej przez obiekt i liczby przekazanej jako parametr. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 24.23. Docz do klasy PolarComplex metod div(), która bdzie zwraca iloraz liczby zespolonej reprezentowanej przez obiekt i liczby przekazanej jako parametr. Napisz program demonstrujcy dziaanie tej metody.
74
Programowanie w jzyku Java
Zadanie 24.24. Docz do klasy PolarComplex metody sqr() i cube(), które bd zwraca kwadrat i szecian liczby zespolonej reprezentowanej przez obiekt. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 24.25. Docz do klasy PolarComplex metod power() z jednym parametrem n typu cakowitego (int), która bdzie zwraca potg o wykadniku n liczby zespolonej reprezentowanej przez obiekt. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 24.26. Liczba zespolona ma dwa pierwiastki kwadratowe. Docz do klasy PolarComplex metod sqrt() z jednym parametrem k typu int, która bdzie zwraca obiekt PolarComplex wskazany przez parametr k — pierwiastek kwadratowy z liczby zespolonej. Napisz program demonstrujcy dziaanie tej metody. Wyznacz reszt z dzielenia k przez 2 (k%2) — reszta 0 lub 1 wskae numer pierwiastka.
Zadanie 24.27. Liczba zespolona ma trzy pierwiastki szecienne (trzeciego stopnia). Docz do klasy PolarComplex metod cbrt() z jednym parametrem k typu int, która bdzie zwraca obiekt PolarComplex wskazany przez parametr k, pierwiastek trzeciego stopnia z liczby zespolonej. Napisz program demonstrujcy dziaanie tej metody. Wyznacz reszt z dzielenia k przez 3 (k%3) — reszta 0, 1 lub 2 wskae numer pierwiastka.
Zadanie 24.28. Docz do klasy PolarComplex bezparametrowe metody sqrt() i cbrt(), które bd zwraca pierwiastki kwadratowe i szecienne z liczby reprezentowanej przez obiekt w postaci tablicy obiektów klasy Complex. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 24.29. Napisz program rozwizujcy w zbiorze liczb zespolonych równanie o wspóczynnikach rzeczywistych: a) az c 2
b) z a 3
0, a z 0 , 0.
Rozdzia 3. i Trzeci krok — budujemy wasne metody i klasy
75
Zadanie 24.30. Napisz program rozwizujcy w zbiorze liczb zespolonych równanie o wspóczynnikach zespolonych: a) az c 2
b) z a 3
0 , a z 0 0i , 0.
Zadanie 24.31. Liczba zespolona ma n pierwiastków n-tego stopnia. Docz do klasy PolarComplex metod root() z dwoma parametrami n i k typu int, która bdzie zwraca obiekt PolarComplex wskazany przez parametr k — pierwiastek n-tego stopnia z liczby zespolonej. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 24.32. Docz do klasy PolarComplex metod root() z jednym parametrem n okrelajcym stopie pierwiastka, która bdzie zwraca tablic obiektów klasy Complex z pierwiastkami n-tego stopnia z liczby zespolonej reprezentowanej przez obiekt (wywoujcy metod). Napisz program demonstrujcy dziaanie tej metody.
Zadanie 24.33. Napisz program wyznaczajcy dla liczby naturalnej n podanej przez uytkownika z klawiatury wszystkie pierwiastki równania: a) z n 1
0,
b) z i
0,
n
c) z
2n
iz n 1 0 .
76
Programowanie w jzyku Java
Rozdzia 4.
Czwarty krok — pliki, tablice i macierze 25. Operacje na plikach tekstowych Zadanie 25.1. Korzystajc z obiektów i metod klasy FileWriter, napisz program zapisujcy do pliku tekstowego tekst.txt jeden wiersz tekstu: Programowanie obiektowe.
Zadanie 25.2. Plik tekstowy tekst.txt zawiera jeden wiersz tekstu: Programowanie obiektowe. Korzystajc z obiektu i metod klasy FileWriter, napisz program dopisujcy do tego pliku w pierwszym wierszu tekst: w jzyku Java, a w kolejnym wierszu tekst: jest bardzo interesujce. W systemie Windows koniec wiersza w pliku tekstowym skada si z dwóch znaków CR (ang. carriage return, warto ASCII 13, znak '\r') i LF (ang. line feed warto ASCII 10, znak '\n'). W systemach UNIX i Linux kocem wiersza jest LF, a w systemie Mac OS — znak CR.
Zadanie 25.3. Korzystajc z obiektu i metod klasy FileWriter, napisz program obliczajcy i zapisujcy w pliku silnia.txt wartoci n! (n silnia) dla n = 1, 2, …, 12. Kady wynik zapisz w odrbnym wierszu, w postaci 12! = 479001600. Przypomnijmy znaczenie symbolu n!: 1! = 1, 2! = 1!·2 = 1·2, 3! = 2!·3 = 1·2·3 itd.
78
Programowanie w jzyku Java
W tym zadaniu i zadaniach podobnych starajmy si, aby plik wyjciowy nie zawiera na kocu pustego wiersza (jeli obecno tego ostatniego wiersza nie jest zamierzona). Taki wiersz moe nam sprawi róne niespodzianki, gdy plik bdzie odczytywany.
Zadanie 25.4. Napisz program zapisujcy w pliku pierwiastki.txt wartoci pierwiastków kwadratowych i szeciennych dla liczb naturalnych od 2 do 15. Kady wiersz pliku powinien zawiera trzy liczby oddzielone znakami tabulatora — liczb naturaln, pierwiastek kwadratowy z tej liczby i pierwiastek szecienny. Pierwiastki podaj z precyzj do 8 miejsc po przecinku. Do formatowania wyników uyj metody format() z klasy String.
Zadanie 25.5. Napisz program zapisujcy w pliku tekstowym sto.txt sto liczb cakowitych wylosowanych z zakresu od 1 do 20. Liczby w pliku powinny by oddzielone odstpami.
Zadanie 25.6. Napisz program zapisujcy w pliku tekstowym dane.txt 50 par liczb. Kada para liczb powinna by umieszczona w odrbnym wierszu. Pierwsza liczba w parze powinna by rzeczywista, dodatnia i nie wiksza od 10 oraz podana z dokadnoci do dwóch miejsc po przecinku, druga liczba powinna by cakowita i ma nalee do przedziau 2, 8 . Liczby w wierszu oddzielamy odstpem. Po rozwizaniu zada 25.1 – 25.6 bdziemy mieli w biecym folderze pi plików: tekst.txt, silnia.txt, pierwiastki.txt, sto.txt i dane.txt. Zawarto tych plików bdziemy odczytywali w kolejnych zadaniach.
Zadanie 25.7. Korzystajc z obiektu i metod klasy FileReader, napisz program odczytujcy zawarto pliku tekstowego i wywietlajcy jego zawarto w konsoli. Bezparametrowa metoda read() z klasy FileReader odczytuje z pliku jeden znak i zwraca jego kod, liczb typu int z zakresu od 0 do 65 535 lub liczb –1, gdy nie mona odczyta znaku. Metoda ready() zwraca warto logiczn true, gdy z pliku mona odczyta kolejny znak, i false w przeciwnym wypadku.
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
79
Zadanie 25.8. Korzystajc z obiektu i metod klasy FileReader, utwórz metod (readLine()) odczytujc wiersz pliku tekstowego. Napisz program odczytujcy i wywietlajcy w konsoli wszystkie wiersze pliku tekstowego. Klasa FileReader nie zawiera metody readLine(), wic musisz j sam zbudowa . Plik tekstowy otwórz przed wywoaniem metody, obiekt (klasy FileReader) skojarzony z plikiem przeka jako parametr do metody readLine(), która przeczytany z pliku wiersz tekstu zwróci w postaci acucha znaków.
Zadanie 25.9. Napisz program wywietlajcy w konsoli kod ródowy programu w jzyku Java wraz z numerami linii. Nazw pliku (bez rozszerzenia) uytkownik powinien podawa z klawiatury. Jeli w okrelonej lokalizacji nie ma wskazanego pliku, to program powinien wywietli odpowiedni komunikat. Do wprowadzenia nazwy pliku z konsoli oraz do odczytania wierszy tekstu z pliku wykorzystaj obiekty klasy BufferedReader i metod readLine() z tej klasy. Obecno pliku moesz sprawdzi , stosujc metod exists() z klasy File.
Zadanie 25.10. Napisz program zapisujcy do pliku kod ródowy programu w jzyku Java wraz z numerami linii. Nazw pliku (bez rozszerzenia) uytkownik powinien podawa z klawiatury. Jeli w okrelonej lokalizacji nie ma wskazanego pliku, to program powinien wywietli odpowiedni komunikat. Nazwa pliku wyjciowego powinna by taka jak nazwa pliku ródowego, rozszerzenie java zamienimy na rozszerzenie txt. Do wprowadzenia nazwy pliku z konsoli oraz do odczytania wierszy tekstu z pliku wykorzystaj obiekty klasy Scanner. Do zapisania pliku wyjciowego uyj metod klasy PrintWriter.
Zadanie 25.11. W pliku tekstowym wpisany jest cig liczb cakowitych oddzielonych odstpami. Napisz program, który odczyta i wywietli w konsoli liczby z pliku oraz obliczy ich sum. Do testów moesz uy pliku sto.txt (rozwizanie zadania 25.5). Nie wykorzystuj jednak faktu, e znasz ilo liczb zapisanych w tym pliku.
80
Programowanie w jzyku Java
Zadanie 25.12. W pliku tekstowym wpisany jest cig liczb cakowitych oddzielonych odstpami. Napisz program, który znajdzie najmniejsz liczb w tym pliku oraz obliczy, ile razy ta liczba w tym pliku wystpuje. Do testów moesz uy pliku sto.txt (rozwizanie zadania 25.5). Nie wykorzystuj jednak faktu, e znasz ilo liczb zapisanych w pliku.
Zadanie 25.13. W pliku tekstowym zapisane s w kolejnych wierszach pary liczb — liczba zmiennoprzecinkowa i liczba cakowita. Napisz program, który odczytuje pary liczb z pliku, oblicza iloczyn kadej pary i sumuje iloczyny. Wynik oblicze naley wypisa w konsoli i zapisa w ostatnim wierszu pliku z danymi. Do testów moesz uy pliku dane.txt (rozwizanie zadania 25.6).
26. Tablice jednowymiarowe i wielomiany Jednym z zastosowa tablic jednowymiarowych moe by przechowywanie wspóczynników wielomianu. Wielomian n-tego stopnia jednej zmiennej w( x) a n x n a n 1 x n 1 ... a1 x a 0 ma n+1 wspóczynników, które moemy zapisa w tablicy double[] a = {a0, a1, ..., an};.
Zadanie 26.1. Napisz program obliczajcy wartoci wielomianu. Stopie wielomianu, wspóczynniki i kolejne wartoci argumentu uytkownik bdzie wprowadza z klawiatury. Podanie argumentu x = 0 bdzie sygnaem do zakoczenia pracy programu. Do obliczenia wartoci wielomianu wykorzystaj schemat Hornera.
Zadanie 26.2. Napisz program, który obliczy i zapisze w pliku tekstowym (wielomian.txt) tablic wartoci wielomianu w( x) 2 x 3 5 x 2 x 3 w przedziale 2, 3 z krokiem h = 0,125. Plik powinien zawiera trzy wiersze z informacjami o rozwizywanym zadaniu, wedug schematu: stopie wielomianu (pierwszy wiersz), wspóczynniki wielomianu oddzielone odstpami w drugim wierszu (zaczynajc od wyrazu wolnego) i krace
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
81
przedziau oraz krok w trzecim wierszu. W kolejnych wierszach umiecimy pary liczb (argument i warto) oddzielone odstpem.
Zadanie 26.3. Napisz program, który obliczy i wywietli w konsoli sum dwóch wielomianów. Skorzystaj z metod dostpnych w klasie Arrays. Przyjmij, e wywietlajc wynik lub prezentujc dane, wielomian w( x) a n x n a n 1 x n 1 ... a1 x a 0 zapiszemy w postaci acucha znaków "w = [a0, a1, ... an]", gdzie a0, a1, …, an s liczbami wyraajcymi wspóczynniki wielomianu.
Zadanie 26.4. Napisz program, który obliczy i wywietli w konsoli rónic dwóch wielomianów. Zob. wskazówk do zadania 26.3.
Zadanie 26.5. Napisz program, który obliczy i wywietli w konsoli iloczyn wielomianu przez liczb.
Zadanie 26.6. Napisz program, który obliczy i wywietli w konsoli iloczyn dwóch wielomianów.
Zadanie 26.7. Napisz program, który obliczy i wywietli w konsoli pochodn wielomianu.
Zadanie 26.8. Napisz program, który obliczy i wywietli w konsoli cak nieoznaczon (funkcj pierwotn) wielomianu.
Zadanie 26.9. Utwórz klas Polynomial (plik Polynomial.java) umoliwiajc wykonywanie podstawowych dziaa na wielomianach zapisanych w postaci tablicy wspóczynników. Napisz aplikacj prezentujc moliwoci utworzonych metod i konstruktorów.
Zadanie 26.10. Napisz program wykonujcy dzielenie wielomianu w( x)
a n x n a n 1 x n 1 ... a1 x a 0
przez dwumian o postaci (x–c).
82
Programowanie w jzyku Java
Zadanie 26.11. Docz do klasy Polynomial dwie metody — division() i remainder() — obliczajce iloraz i reszt z dzielenia wielomianu reprezentowanego przez obiekt wywoujcy metod przez dwumian (x-c), gdzie liczba c typu double jest parametrem wywoania metody. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 26.12. b
³ w( x)dx dla wielomianu
Napisz program obliczajcy cak oznaczon s
a
w( x)
a n x n a n 1 x n 1 ... a1 x a 0
Wszystkie potrzebne dane uytkownik powinien wprowadzi z klawiatury — najpierw dane wielomianu (stopie i wspóczynniki), a pó niej granice cakowania. Do wyznaczenia funkcji pierwotnej uyj metody (integral()) opracowanej w rozwizab
niach zada 26.8 i 26.9, a nastpnie skorzystaj ze wzoru
³ w( x)dx
F (b) F (a) .
a
Zadanie 26.13. Majc dane wszystkie pierwiastki rzeczywiste wielomianu ( x1 , x2 , ..., xn ), napisz program wyznaczajcy wspóczynniki wielomianu.
27. Obliczenia statystyczne Zadania 27.1 – 27.19 wykonamy dla n-elementowej próbki zapisanej w tablicy: double[] x = {1.35, 2.45, 2.05, 1.20, 2.15, 1.70, 1.45, 1.95, 2.00, 1.65, 1.65, 2.05, 1.75, 1.25, 2.25, 1.40};
Czytelnik moe samodzielnie zmieni zestaw danych lub sposób ich pobierania przez program — wprowadzanie danych z klawiatury lub odczytywanie z pliku. Naley zwróci uwag na rozbienoci pomidzy zakresem indeksów. W tablicach w jzyku Java indeksowanie rozpoczynamy od 0 i koczymy na indeksie o 1 mniejszym od rozmiaru tablicy, natomiast we wzorach statystyki opisowej indeksy wartoci próbki bd w granicach od 1 do n. W zadaniach bardzo czsto bdziemy mieli do czynienia z obliczaniem sumy cigu n
liczb x1, x2, …, xn (oznaczanej symbolem
¦ x ) zapisanego w tablicy x[0], x[1], …, i
i 1
x[n–1]. Zrealizujemy to przy uyciu instrukcji ptli: double suma = 0; for(double xi: x) suma += xi;
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
83
lub: double suma = 0; for(int i = 0; i < n; ++i)) suma += x[i];
Zadanie 27.1. Dla podanej próbki n-elementowej x1, …, xn wyznacz najmniejsz i najwiksz warto w cigu oraz rozstp badanej cechy. Rozstpem badanej cechy jest rónica pomidzy wartoci maksymaln i minimaln
R
xmax xmin .
Zadanie 27.2. Dla podanej próbki n-elementowej x1, …, xn wyznacz redni arytmetyczn.
redni arytmetyczn liczb x1, …, xn nazywamy liczb
x
1 n ¦ xi ni1
.
Zadanie 27.3. Dla podanej próbki n-elementowej x1, …, xn wyznacz redni geometryczn. n
redni geometryczn dodatnich liczb x1, …, xn nazywamy liczb
g
n
x
i
.
i 1
Jeeli wszystkie xi > 0, to
log g
1 n ¦ log xi ni1
.
Zadanie 27.4. Dla podanej próbki n-elementowej x1, …, xn wyznacz redni harmoniczn. redni harmoniczn rónych od zera liczb x1, …, xn nazywamy liczb
h
§1 n 1 · ¨¨ ¦ ¸¸ © n i 1 xi ¹
1
n
, gdy
¦
i 1
1 z 0 xi
(odwrotno redniej arytmetycznej
odwrotnoci tych liczb).
Zadanie 27.5. Dla podanej próbki n-elementowej x1, …, xn wyznacz redni potgow rzdu r. Obliczenia wykonaj dla r = 2 i r = 3.
84
Programowanie w jzyku Java
redni potgow rzdu r dodatnich liczb x1, …, xn nazywamy liczb
p (r )
r
1 n
n
¦x
r i
. Dla r
1 otrzymujemy redni harmoniczn ( p ( 1)
1 redni arytmetyczn ( p (1)
a dla r
h ),
i 1
x ).
Zadanie 27.6. Dla podanej próbki n-elementowej x1, …, xn wyznacz median. Posortuj tablic z danymi i wybierz element rodkowy, gdy n jest nieparzyste, lub oblicz redni arytmetyczn dwóch rodkowych liczb, gdy n jest parzyste:
me
x n1 , gdy n jest nieparzyste °° 2 ®1 § · ° ¨¨ x n x n ¸¸, gdy n jest parzyste 1 °¯ 2 © 2 2 ¹
Naley pamita o przesuniciu indeksu wynikajcego z rónicy pomidzy indeksami we wzorach a indeksami w tablicach.
Zadanie 27.7. Wyznacz warto modaln (dominant) n-elementowej próbki x1, …, xn. Wartoci modaln (dominant, mod) próbki x1, …, xn o powtarzajcych si wartociach nazywamy najczciej powtarzajc si warto , o ile taka istnieje. Ponadto warto ta nie moe by wartoci minimaln lub maksymaln.
Zadanie 27.8. Oblicz wariancj n-elementowej próbki x1, …, xn. Wykorzystaj wszystkie niej podane wzory i porównaj uzyskane wyniki. Wariancj s2 (dyspersj) próbki x1, …, xn nazywamy redni arytmetyczn kwadratów odchyle wartoci xi od redniej arytmetycznej x próbki: s 2 Mona zastosowa wzory równowane s 2
s
2
1 n
n
1 n
n
¦x
2 i
x 2 lub
i 1
¦ x a x a , gdzie a jest dowoln sta. 2
i
i 1
2
1 n
n
¦ x x
2
i
i 1
.
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
85
Zadanie 27.9. Oblicz odchylenie standardowe n-elementowej próbki x1, …, xn. Odchylenie standardowe s próbki x1, …, xn jest równe pierwiastkowi kwadratowemu z wariancji s2 (zob. zadanie 27.8).
Zadanie 27.10. Oblicz odchylenie przecitne d próbki x1, …, xn od staej a. Obliczenia wykonaj dla a = 2. Odchyleniem przecitnym d od staej a próbki x1, …, xn nazywamy redni arytmetyczn wartoci bezwzgldnych odchyle poszczególnych wartoci xi od staej a:
d
1 n
n
¦ x a . i
i 1
Zadanie 27.11. Oblicz odchylenie przecitne d1 próbki x1, …, xn od wartoci redniej x .
Zadanie 27.12. Oblicz odchylenie przecitne d2 próbki x1, …, xn od mediany me .
Zadanie 27.13. Wyznacz kwartyl dolny Q1 i kwartyl górny Q3 próbki x1, …, xn. Oblicz odchylenie wiartkowe Q. Wartoci uporzdkowanej próbki dzielimy na dwie grupy: wartoci mniejsze od mediany i median oraz median i wartoci wiksze od mediany. Kwartylem dolnym (Q1) jest mediana pierwszej grupy, a górnym (Q3) mediana drugiej grupy. OdchyleQ3 Q1 nie wiartkowe Q obliczamy ze wzoru Q . 2
Zadanie 27.14. Oblicz moment zwyky ml rzdu l próbki x1, …, xn. Obliczenia wykonaj dla l = 2, 3 i 4.
Wzór ml
1 n
n
¦x , l i
i 1
lN .
86
Programowanie w jzyku Java
Zadanie 27.15. Oblicz moment centralny Ml rzdu l próbki x1, …, xn. Obliczenia wykonaj dla l = 2, 3 i 4. n
¦ (x x) ,
1 n
Wzór M l
l
i
l N . Z wasnoci redniej arytmetycznej wynika, e
i 1
M1 = 0, natomiast M2 jest wariancj.
Zadanie 27.16. Oblicz moment absolutny zwyky al rzdu l próbki x1, …, xn. Obliczenia wykonaj dla l = 2, 3 i 4. 1 n
Wzór al
n
¦| x | , l
i
lN .
i 1
Zadanie 27.17. Oblicz moment absolutny centralny bl rzdu l próbki x1, …, xn. Obliczenia wykonaj dla l = 2, 3 i 4. 1 n
Wzór bl
n
¦| x x | , l
i
l N . Absolutny moment centralny rzdu pierwszego
i 1
jest odchyleniem przecitnym od redniej arytmetycznej.
Zadanie 27.18. Oblicz wspóczynnik zmiennoci v próbki x1, …, xn.
Wzór v
s 100% , gdzie s jest odchyleniem standardowym, a x redni arytmex
tyczn próbki.
Zadanie 27.19. Oblicz wspóczynnik nierównomiernoci H próbki x1, …, xn.
Wzór H tycznej x .
d1 100% , gdzie d1 jest odchyleniem przecitnym od redniej arytmex
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
87
W zadaniach 27.1 – 27.19 przedstawiono podstawowe wzory zwizane z obliczeniami statystyki opisowej dla pojedynczej próbki, zwykle nieprzekraczajcej 30 elementów. Czytelnik moe samodzielnie na podstawie rozwiza tych zada konstruowa programy majce na celu rozwizywanie problemów z zakresu statystyki.
Zadanie 27.20. Na podstawie problemów zawartych w zadaniach 27.1 – 27.19 utwórz klas Stat zawierajc metody statyczne do oblicze statystycznych. Napisz aplikacj konsolow pokazujc dziaanie wybranych metod z klasy Stat. Sporzd dokumentacj tej klasy.
Zadanie 27.21. Na podstawie problemów zawartych w zadaniach 27.1 – 27.19 utwórz klas Statpr umoliwiajc utworzenie obiektu (próbki) zawierajcego metody do rozwizywania tych problemów. Napisz aplikacj konsolow pokazujc dziaanie wybranych metod z klasy Statpr. Sporzd dokumentacj tej klasy.
28. Tablice wielowymiarowe i macierze Zadanie 28.1. Utwórz dwuwymiarow tablic liczb cakowitych o trzech wierszach. W pierwszym wierszu tablicy umie liczby od 1 do 10, w drugim kwadraty tych liczb, a w trzecim szeciany liczb z pierwszego wiersza. Napisz program tworzcy i wywietlajcy t tablic w konsoli.
Zadanie 28.2. W tablicy dwuwymiarowej nie wszystkie wiersze musz mie ten sam rozmiar. Napisz program, który utworzy tablic liczb cakowitych o dziesiciu wierszach. Wypenij tablic kolejnymi liczbami naturalnymi, zaczynajc od liczby 1. W pierwszym wierszu umie jedn liczb, w drugim dwie liczby, w trzecim trzy itd. — w dziesitym dziesi liczb. Oblicz sumy liczb w kolejnych wierszach i sum wszystkich liczb zapisanych w tablicy. Wywietl w konsoli tablic liczb oraz obliczone sumy.
Zadanie 28.3. Utwórz klas TInt, która bdzie zawiera metody statyczne input() i print() umoliwiajce wprowadzanie danych z konsoli do tablicy lub wywietlanie danych z tablicy w konsoli. Parametrem wywoania tych metod powinna by tablica liczb cakowitych jedno- lub dwuwymiarowa. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 28.4. Utwórz w klasie TInt metod statyczn setRandom(), która wypeni tablic liczb cakowitych wartociami wylosowanymi z zakresu od 0 do n (liczba cakowita n > 0).
88
Programowanie w jzyku Java
Tablic oraz zakres wartoci podaj jako parametry metody. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.5. Dodaj do klasy TInt metod statyczn printf() wywietlajc tablic liczb cakowitych w konsoli. Metoda ta powinna mie dwa parametry: acuch formatujcy i identyfikator tablicy. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.6. Na podstawie zada 28.3, 28.4 i 28.5 utwórz klas TDouble z metodami statycznymi input(), print(), printf() i setRandom(), uatwiajcymi pobieranie i wypisywanie danych oraz losowe ustawianie wartoci w jedno- i dwuwymiarowych tablicach liczb zmiennoprzecinkowych typu double. Napisz program pokazujcy dziaanie wybranych metod z tej klasy. Macierz jest uporzdkowan prostoktn tablic liczb, dla której zdefiniowane s dziaania algebraiczne dodawania (odejmowania) i mnoenia: Dodawanie (odejmowanie) dwóch macierzy jest moliwe tylko dla macierzy
o jednakowych liczbach kolumn (n) i wierszy (m). Suma (rónica) macierzy A i B jest macierz C tak, e cij aij bij ( cij aij bij ). Mnoenie macierzy jest moliwe, gdy liczba kolumn pierwszej macierzy (m)
jest równa liczbie wierszy drugiej macierzy. Iloczyn macierzy A i B jest m
macierz C tak, e cij
¦ aik bkj . Mnoenie macierzy nie jest przemienne. k 1
Zawsze okrelone jest mnoenie macierzy przez liczb O , polegajce na
pomnoeniu kadego elementu macierzy przez t liczb ( cij
Oaij ).
Macierze moemy przedstawia w programach jako tablice dwuwymiarowe. Naley pamita, e tablice s indeksowane od zera, a indeksy macierzy rozpoczynamy od jedynki.
Zadanie 28.7. Utwórz metod sum() dodajc dwie macierze zapisane w postaci tablic dwuwymiarowych. Napisz program demonstrujcy dziaanie metody sum(). W tym i kolejnych zadaniach do wprowadzania danych uywaj metod z klasy TInt lub TDouble.
Zadanie 28.8. Utwórz metod difference() obliczajc rónic dwóch macierzy zapisanych w postaci tablic dwuwymiarowych. Napisz program demonstrujcy dziaanie metody difference().
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
89
Zadanie 28.9. Utwórz metod product() obliczajc iloczyn dwóch macierzy zapisanych w postaci tablic dwuwymiarowych. Napisz program demonstrujcy dziaanie metody product().
Zadanie 28.10. Utwórz metod product() obliczajc iloczyn macierzy zapisanej w postaci tablicy dwuwymiarowych przez liczb. Napisz program demonstrujcy dziaanie metody product().
Zadanie 28.11. Zbuduj metod transp() tworzc macierz transponowan z macierzy podanej jako parametr metody. Napisz program demonstrujcy dziaanie metody transp(). Macierz transponowana (przestawiona) powstaje z danej macierzy poprzez zamian jej wierszy na kolumny i kolumn na wiersze.
Zadanie 28.12. Utwórz metod statyczn toDouble() konwertujc macierz o elementach cakowitych na macierz o elementach zmiennoprzecinkowych. Napisz program demonstrujcy dziaanie tej metody. Docz j do klasy TInt.
Zadanie 28.13. Docz do klasy TDouble metod statyczn o nazwie valueOf(), zwracajc tablic (macierz) z elementami typu double o elementach odpowiadajcych elementom tablicy (macierzy) liczb cakowitych. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.14. W klasie TDouble utwórz statyczn metod toInt(), która bdzie zwraca tablic (macierz) o wartociach cakowitych, odpowiadajcych (zamiana przez rzutowanie) tablicy liczb zmiennoprzecinkowych podanej jako parametr. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.15. W klasie TInt utwórz statyczn metod valueOf(), która bdzie budowa tablic (macierz) o wartociach cakowitych, odpowiadajcych (zamiana przez rzutowanie) tablicy liczb zmiennoprzecinkowych podanej jako parametr. Napisz program demonstrujcy dziaanie tej metody. Macierze, w których liczba wierszy jest równa liczbie kolumn, nazywamy macierzami kwadratowymi. Z macierzami kwadratowymi zwizany jest szereg poj, takich jak: lad macierzy, wyznacznik macierzy, macierz diagonalna, macierz trójktna, macierz jednostkowa i macierz odwrotna.
90
Programowanie w jzyku Java
Zadanie 28.16. Utwórz statyczn metod trace() wyznaczajc lad macierzy. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.17. Utwórz statyczn metod getI() zwracajc macierz jednostkow stopnia n (stopie podamy jako parametr wywoania metody). Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.18. Utwórz statyczn metod setI() tworzc z macierzy kwadratowej podanej jako parametr macierz jednostkow. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.19. Utwórz metod statyczn det() obliczajc wyznacznik macierzy kwadratowej. Do obliczenia wyznacznika uyj rozwinicia Laplace’a. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.20. Utwórz metod statyczn upperTriangular() przeksztacajc macierz kwadratow podan jako parametr na macierz trójktn górn. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.21. Utwórz metod statyczn lowerTriangular() przeksztacajc macierz kwadratow podan jako parametr na macierz trójktn doln. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.22. Utwórz metod statyczn diagonal() przeksztacajc macierz kwadratow podan jako parametr na macierz diagonaln. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.23. Utwórz metod statyczn inverse() obliczajc i zwracajc macierz odwrotn do macierzy kwadratowej podanej jako parametr. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.24. Napisz program rozwizujcy ukad n-równa liniowych z n niewiadomymi (n < 10). Ukad równa rozwi, stosujc metod wyznaczników. Wszystkie niezbdne metody umie w klasie programu.
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
91
Zadanie 28.25. Napisz program rozwizujcy ukad n-równa liniowych z n niewiadomymi. Ukad równa rozwi, stosujc rachunek macierzy: A X B , X A 1 B , gdzie A — macierz podstawowa ukadu, X — wektor niewiadomych, B — kolumna wyrazów wolnych. Wszystkie niezbdne metody umie w klasie programu.
Zadanie 28.26. Napisz program rozwizujcy ukad n-równa liniowych z n niewiadomymi. Ukad równa rozwi, stosujc metod eliminacji. Wszystkie niezbdne metody umie w klasie programu.
Zadanie 28.27. Utwórz klas Matrix, która na podstawie tablic dwuwymiarowych, podanych wymiarów macierzy lub innych obiektów klasy Matrix (konstruktor kopiujcy) bdzie umoliwia tworzenie obiektów reprezentujcych macierze. Utwórz metody uatwiajce dostp do elementów macierzy (pól obiektu), wprowadzanie i wywietlanie danych oraz wypenianie macierzy wartociami losowymi. Napisz program demonstrujcy dziaanie metod klasy Matrix.
Zadanie 28.28. Docz do klasy Matrix metody umoliwiajce wykonywanie podstawowych dziaa na macierzach: dodawanie, odejmowanie i mnoenie macierzy oraz mnoenie macierzy przez skalar. Napisz program demonstrujcy dziaania na macierzach.
Zadanie 28.29. Docz do klasy Matrix metody umoliwiajce przeksztacanie macierzy kwadratowych na posta trójktn lub diagonaln. Napisz program demonstrujcy dziaanie tych metod.
Zadanie 28.30. Docz do klasy Matrix metod umoliwiajc obliczanie wyznacznika macierzy. Napisz program demonstrujcy dziaanie tej metody.
Zadanie 28.31. Docz do klasy Matrix metod umoliwiajc obliczanie macierzy odwrotnej. Napisz program demonstrujcy obliczanie macierzy odwrotnej. Sprawd uzyskany wynik, wykonujc odpowiednie mnoenie.
Zadanie 28.32. Wykorzystujc moliwoci klasy Matrix i obliczenia na macierzach, rozwi ukad n-równa liniowych z n niewiadomymi.
92
Programowanie w jzyku Java
Zadanie 28.33. Wykorzystujc moliwoci klasy Matrix i metod wyznaczników, rozwi ukad n-równa liniowych z n niewiadomymi. Utwórz metod pomocnicz replaceCol(), która w macierzy wywoujcej t metod zastpi wskazan kolumn kolumn przekazan jako parametr (bdzie to kolumna wyrazów wolnych).
29. Obliczanie wartoci funkcji, rekurencja i inne zadania Zadanie 29.1. Napisz aplikacj testujc dziaanie podanej metody dla rónych argumentów. Okrel, co oblicza ta metoda. Nadaj jej odpowiedni nazw. static double f(double x) { return (x > 0)?x: x; }
Zadanie 29.2. x, gdy x d y x, gdy x t y oraz max( x, y ) ® . ® ¯ y, gdy x ! y ¯ y, gdy x y Utwórz klas MinMax z metodami min() i max() obliczajcymi i zwracajcymi wartoci tych funkcji. Napisz aplikacj pokazujc dziaanie tych metod.
Okrelono dwie funkcje: min( x, y )
Zadanie 29.3. 1, gdy x 0 ° Okrelono funkcj f ( x) ®0, gdy x 0 . Co oblicza ta funkcja? Utwórz metod ob°1, gdy x ! 0 ¯ liczajc warto tej funkcji. Napisz aplikacj pokazujc dziaanie zbudowanej metody.
Zadanie 29.4. 0, gdy x 0 ° Okrelono funkcj f ( x) ® x . Co oblicza ta funkcja? Utwórz metod ob° , gdy x z 0 ¯x liczajc warto tej funkcji. Napisz aplikacj pokazujc dziaanie zbudowanej metody.
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
93
Zadanie 29.5. Napisz aplikacj testujc wartoci funkcji okrelonych wzorami: a) f x, y
x y x y
b) g x, y
x y x y
c) h( x)
2
2
f ( x, x)
Co obliczaj te funkcje? Utworzonym metodom nadaj odpowiednie nazwy.
Zadanie 29.6. Napisz definicje metod square() i cube() obliczajcych kwadrat i szecian liczby x. Zastosuj utworzone metody do obliczenia kwadratów i szecianów liczb: a) cakowitych od 1 do 15, b) rzeczywistych od 1 do 3 z krokiem 0,25.
Zadanie 29.7. Potg o wykadniku cakowitym dodatnim okrelamy wzorem a n
a a
... a . Utwórz n
metod adoen() obliczajc an. Napisz aplikacj pokazujc dziaanie tej metody.
Zadanie 29.8. Potg o wykadniku cakowitym nieujemnym moemy okreli wzorem rekurencyj1, dla n 0 . Napisz definicj metody rekurencyjnej adoen() oblinym: a n ® n 1 ¯a a , dla n ! 0 czajcej an oraz aplikacj pokazujc dziaanie tej metody.
Zadanie 29.9. Szybkie potgowanie — inn wersj metody rekurencyjnej obliczajcej an (szybsz ze wzgldu na mniejsz liczb wywoa rekurencyjnych i zredukowanie liczby mnoe) moemy zrealizowa na podstawie wzoru:
an
° °1 dla n 0 ° § n 1 · 2 ° 2 ®a ¨ a ¸ dla n nieparzystego (n ! 0) . © ¹ ° ° n 2 °§¨ a 2 ·¸ dla n parzystego (n ! 0) ¯°© ¹
94
Programowanie w jzyku Java
Utwórz metod adoen() obliczajc an. Napisz aplikacj pokazujc dziaanie tej metody.
Zadanie 29.10. Potg o podstawie a rónej od 0 i wykadniku cakowitym n moemy zdefiniowa a a ... a, dla n ! 0 °
n ° n . w nastpujcy sposób: a ®1, dla n 0 °1 ° n , dla n 0 ¯a Napisz definicj metody power() (prototyp: double power(double a, int n)) obliczajcej an dla dowolnej liczby cakowitej oraz aplikacj pokazujc dziaanie tej funkcji. Funkcj adoen (zob. zadanie 29.7, 29.8 lub 29.9) obliczajc an dla n > 1 wykorzystamy w funkcji power (do obliczania a n lub a n
1 dla n 1, 2, 3, ... ). an
Zadanie 29.11. Pierwiastek drugiego stopnia z liczby dodatniej a moemy obliczy metod iteracyjn na podstawie wzoru x
1§ a· ¨ x ¸ , przyjmujc jako pierwsze przyblienie x x¹ 2©
1 . Ob-
liczenia kontynuujemy do chwili, gdy rónica pomidzy dwoma kolejnymi przyblieniami pierwiastka bdzie dostatecznie maa. Napisz metod sqrt() (ang. square root) obliczajc pierwiastek kwadratowy z podanej liczby dodatniej. Zbuduj aplikacj pokazujc dziaanie metody sqrt() i porównujc otrzymane wyniki z wynikami metody bibliotecznej Math.sqrt().
Zadanie 29.12. Pierwiastek trzeciego stopnia z liczby dodatniej a moemy obliczy metod iteracyjn na podstawie wzoru x 1 §¨ 2 x a ·¸ , przyjmujc jako pierwsze przyblienie x 1 . Obx2 ¹ 3© liczenia kontynuujemy do chwili, gdy rónica pomidzy dwoma kolejnymi przyblieniami pierwiastka bdzie dostatecznie maa. Napisz metod cbrt() (ang. cube root) obliczajc pierwiastek trzeciego stopnia z podanej liczby dodatniej. Zbuduj aplikacj pokazujc dziaanie metody cbrt() i porównujc otrzymane wyniki z wynikami metody bibliotecznej Math.cbrt(). Podany wzór wynika z metody Newtona-Raphsona — iteracyjnego algorytmu wyznaczania przyblionej wartoci pierwiastka funkcji. Dotyczy to równie wzoru z zadania 29.11.
Rozdzia 4. i Czwarty krok — pliki, tablice i macierze
95
Zadanie 29.13. Pierwiastek n-tego stopnia z liczby dodatniej a moemy obliczy metod iteracyjn na podstawie wzoru x 1 §¨ n 1 x a ·¸ , przyjmujc jako pierwsze przyblienie n© x n 1 ¹ x 1 . Obliczenia kontynuujemy do chwili, gdy rónica pomidzy dwoma kolejnymi przyblieniami pierwiastka bdzie dostatecznie maa. Na podstawie podanego wzoru napisz metod nRoot() obliczajc pierwiastek n-tego stopnia z podanej liczby dodatniej. Zbuduj aplikacj pokazujc dziaanie metody nRoot() i porównujc otrzymane wyniki z wynikami uzyskanymi przy zastosowaniu funkcji bibliotecznej. 1
Poniewa n a a n , to warto pierwiastka moemy obliczy przy zastosowaniu funkcji Math.pow(a, 1.0/n).
Skorzystaj z opracowanej w zadaniu 29.7 metody power() do obliczania wartoci x n 1 .
Zadanie 29.14. W klasie Math zdefiniowano metody obliczajce funkcje hiperboliczne — sinus hiperboliczny (Math.sinh()) i cosinus hiperboliczny (Math.cosh()). Napisz program wywietlajcy na ekranie tablice wszystkich funkcji hiperbolicznych w przedziale 5, 5 z krokiem 0,1. Wyniki oblicze zapisz w pliku tekstowym FunkcjeHiperboliczne.txt. Wyniki pracy programu mona zapisa w pliku tekstowym, stosujc w konsoli polecenie: java Z29 14 > FunkcjeHiperboliczne.txt
(przyjmujemy, e rozwizanie zadania zapisano w pliku ródowym Z29 14.java).
Zadanie 29.15. W klasie Math zdefiniowano metod Math.exp() obliczajc warto funkcji wykadniczej e x . Rozwi zadanie 29.14, nie korzystajc z metod Math.sinh() i Math.cosh().
Wartoci funkcji mona wyliczy na podstawie wzorów: sinh x
cosh x
e x e x itp. 2
e x e x , 2
96
Programowanie w jzyku Java
Zadanie 29.16. Zbuduj klas FH (funkcje hiperboliczne) zawierajc metody statyczne obliczajce wartoci wszystkich funkcji hiperbolicznych i funkcji do nich odwrotnych. Napisz aplikacj pokazujc dziaanie tych metod.
Zadanie 29.17. Zbuduj klas FTD, która bdzie zawiera metody statyczne obliczajce warto szeciu funkcji trygonometrycznych i szeciu funkcji do nich odwrotnych. Argumenty funkcji trygonometrycznych i wartoci funkcji odwrotnych powinny by wyraane w stopniach. Udostpnij równie metody konwersji stopni na radiany i radianów na stopnie. Napisz aplikacj pokazujc moliwoci metod statycznych zawartych w tej klasie.
Zadanie 29.18. Zbuduj klas FTR, która bdzie zawiera metody statyczne obliczajce warto szeciu funkcji trygonometrycznych i szeciu funkcji do nich odwrotnych. Argumenty funkcji trygonometrycznych i wartoci funkcji odwrotnych powinny by wyraane w radianach. Udostpnij równie metody konwersji stopni na radiany i radianów na stopnie. Napisz aplikacj pokazujc moliwoci metod statycznych zawartych w tej klasie.
Rozdzia 5.
Rozwizania zada 1. Historia Javy i pierwsze zadania Zadanie 1.1. Podane rozwizanie ma charakter pogldowy i byo w caoci aktualne, gdy powstawa ten tekst. Zmiany na stronach producenta Javy spowodoway, e Czytelnik nie moe dokadnie wykorzysta tego rozwizania i musi, wzorujc si na nim, samodzielnie pobra i zainstalowa rodowisko JDK.
Zakadamy, e dysponujesz komputerem klasy PC z systemem operacyjnym Windows XP lub nowszym i dostpem do internetu. Wykonaj nastpujce czynnoci: 1. Otwórz stron internetow firmy Oracle http://www.oracle.com/pl/index.html. 2. Przejd do dziau Do pobrania. 3. Odszukaj link Java SE i przejd do tej podstrony. 4. Wybierz wersj Java 6 Update 27 i klikajc przycisk Download, pobierz JDK
(Java Development Kit) — http://www.oracle.com/technetwork/java/javase/ downloads/jdk-6u27-download-440405.html. 5. Zapoznaj si z licencj i zaakceptuj j. 6. Wybierz plik instalacyjny waciwy dla posiadanego systemu operacyjnego
i zapisz go na swoim dysku lokalnym: jdk-6u27-windows-i586.exe (76,81 MB) — dla systemu 32-bitowego, jdk-6u27-windows-x64.exe (67,40 MB) — dla systemu 64-bitowego. 7. Otwórz zapisany plik instalacyjny i przeprowad proces instalacji.
98
Programowanie w jzyku Java
Podczas typowej instalacji rodowisko JDK zostanie zainstalowane w folderze C:\Program Files\Java\jdk1.6.0 27\bin1. Pliki binarne (wykonywalne) znajduj si w podfolderze \bin. Naley doda do systemowej cieki przeszukiwa ciek C:\Program Files\Java\jdk1.6.0 27\bin (lub inn, wynikajc z przebiegu instalacji). W Panelu sterowania otwórz aplet System i przejd do zakadki Zaawansowane. Kliknij przycisk Zmienne rodowiskowe, na licie Zmienne uytkownika odszukaj i edytuj zmienn Path (dopisz potrzebn ciek).
Zadanie 1.2. Otwórz konsol (w Windows: Start/Uruchom… — w polu edycyjnym w pisz polecenie cmd i kliknij przycisk OK), wpisz w konsoli polecenie java i nacinij Enter. Jeli w konsoli zostanie wywietlona informacja o sposobie uruchomiania programu (help), to znaczy, e masz zainstalowane rodowisko uruchomieniowe Javy (JRE). Po wpisaniu polecenia java –version uzyskasz informacj o wersji posiadanej maszyny wirtualnej Javy. Wpisz w konsoli polecenie javac. Jeli w konsoli pojawi si informacja o sposobie i opcjach uruchomienia kompilatora, to masz poprawnie zainstalowane rodowisko JDK. Moesz sprawdzi wersj kompilatora (javac –version). Niepowodzenie testu, w postaci komunikatu: Nazwa 'javac' nie jest rozpoznawana jako polecenie wewntrzne lub zewntrzne, program wykonywalny lub plik wsadowy , nie wiadczy o braku JDK. By moe nie zostaa poprawnie ustawiona cieka dostpu (path) do folderu bin zawierajcego kompilator javac.exe. Sprawd to.
Zadanie 1.3. Uruchom aplikacj w linii komend i przekieruj wywietlane dane do pliku, np. java –? > java.txt lub java –help > java.txt (wystarczy równie polecenie java > java.txt). Nastpnie w dowolnym edytorze tekstowym sformatuj ten tekst wedug swoich potrzeb i wydrukuj. Moesz przetumaczy opisy (ale nie sowa bdce opcjami!) na jzyk polski, np.: ? ?
help help
print this help message wywietl komunikat pomocy
Wydrukuj „cigawk”, czsto z niej zapewne skorzystasz. Usage: java [-options] class [args...] (to execute a class) or java [-options] -jar jarfile [args...] (to execute a jar file) where options include: client to select the "client" VM -server to select the "server" VM -hotspot is a synonym for the "client" VM [deprecated]. The default VM is client. -cp -classpath A ; separated list of directories, JAR archives, and ZIP archives to search for class files.
1
Wersja 32 bitowa JDK w 64 bitowym systemie operacyjnym Windows 7 zainstaluje si w folderze C:\Program Files (x86)\Java\jdk1.6.0 27\bin.
Rozdzia 5. i Rozwizania zada
99
-D= set a system property -verbose[:class|gc|jni] enable verbose output -version print product version and exit -version: require the specified version to run -showversion print product version and continue -jre-restrict-search | -jre-no-restrict-search include/exclude user private JREs in the version search -? -help print this help message -X print help on non standard options -ea[:...|:] -enableassertions[:...|:] enable assertions -da[:...|:] -disableassertions[:...|:] disable assertions -esa | -enablesystemassertions enable system assertions -dsa | -disablesystemassertions disable system assertions -agentlib:[=] load native agent library , e.g. agentlib:hprof, see also, agentlib:jdwp=help and agentlib:hprof=help -agentpath:[=] load native agent library by full pathname -javaagent:[=] load Java programming language agent, see java.lang.instrument -splash: show splash screen with specified image
Zadanie 1.4. Uruchomienie aplikacji javac.exe bez podania parametrów powoduje wywietlenie nastpujcej instrukcji: Usage: javac where possible options include: -g Generate all debugging info -g:none Generate no debugging info -g:{lines,vars,source} Generate only some debugging info -nowarn Generate no warnings -verbose Output messages about what the compiler is doing -deprecation Output source locations where deprecated APIs are used -classpath Specify where to find user class files and annotation processors -cp Specify where to find user class files and annotation processors -sourcepath Specify where to find input source files -bootclasspath Override location of bootstrap class files -extdirs Override location of installed extensions -endorseddirs Override location of endorsed standards path -proc:{none,only} Control whether annotation processing and/or compilation is done. -processor [,,...] Names of the annotation processors to run; bypasses default discovery process -processorpath Specify where to find annotation processors -d Specify where to place generated class files -s Specify where to place generated source files -implicit:{none,class} Specify whether or not to generate class files for implicitly referenced files -encoding Specify character encoding used by source files -source Provide source compatibility with specified release -target Generate class files for specific VM version -version Version information -help Print a synopsis of standard options
100
Programowanie w jzyku Java -Akey[=value] -X -J
Options to pass to annotation processors Print a synopsis of nonstandard options Pass directly to the runtime system
Przechwycenie tego tekstu poleceniem javac > opis.txt do pliku opis.txt si nie powiedzie. Moemy natomiast tekst w konsoli zaznaczy (menu wywoane prawym przyciskiem myszy) i skopiowa zaznaczony fragment lub cay tekst do schowka (naciskajc klawisz Enter).
Zadanie 1.5. 1. Plik console.bat — otwieranie konsoli w biecym folderze. cmd
Moesz ten plik wsadowy rozbudowa tak, aby automatycznie wywoywa kolejne dwa pliki wsadowe. call setpath call setdrive cls cmd
Do pliku console.bat utwórz skrót na pulpicie lub w innym dogodnym miejscu. 2. Plik setpath.bat — ustawianie cieki dostpu do folderu bin na komputerach,
na których nie mamy uprawnie do zmian konfiguracyjnych w systemie lub nie chcemy tych zmian dokonywa2. path C:\Program Files\Java\jdk1.6.0 27\bin; %PATH%
3. Plik setdrive.bat — ustawienie folderu z plikami ródowymi jako dysku X:3. subst X: H:\!JAVA ZZ\Pliki X:
4. Plik kompiluj.bat — kompilacja pliku ródowego o nazwie podanej jako
parametr dla pliku wsadowego (nazw podamy bez rozszerzenia .java i to jest nasze mae uproszczenie pracy). javac %1.java
Moemy ten plik rozbudowa, dodajc ciek do kompilatora. C:\Program Files\Java\jdk1.6.0 27\bin\javac %1.java
5. Plik uruchom.bat — uruchomienie wirtualnej maszyny Javy (JVM)
i przekazanie do wykonania kodu skompilowanej klasy. Nazw klasy podajemy jako parametr pliku wsadowego (tu adnego uproszczenia pracy nie wida). java %1 2
3
Na komputerze Czytelnika cieka moe by inna, zalena od tego, gdzie zainstalowano JDK. Autor uywa cieki dla standardowego przebiegu procesu instalacji rodowiska Javy. Autor w czasie opracowywania niniejszego zbioru zada korzysta z pendrive’a, który instalowa si w systemie jako dysk H:. Na materiay zwizane z tworzonym zbiorem autor utworzy folder !JAVA ZZ, a pliki ródowe zapisywa w folderze !JAVA ZZ\Pliki. Na komputerze Czytelnika cieka z plikami moe by inna.
Rozdzia 5. i Rozwizania zada
101
Program cmd.exe umoliwia uycie dziesiciu zmiennych do oznaczania parametrów pliku wsadowego (od %0 do %9). Zmienna %0 przekazuje nazw pliku wsadowego, a zmienne od %1 do %9 zawieraj kolejne argumenty wpisane przez uytkownika w wierszu polecenia. Moemy zatem do pliku wsadowego przekaza nazw klasy (%1) i maksymalnie 8 parametrów (od %2 do %9). java %1 %2 %3 %4 %5 %6 %7 %8 %9
6. Plik edytuj.bat — uruchomienie systemowego Notatnika (notepad.exe)
i przekazanie do edycji kodu ródowego klasy. Nazw klasy podajemy jako parametr pliku wsadowego (nazwa pliku powstanie z nazwy klasy i rozszerzenia .java). start notepad.exe %1.java
Przypomnijmy na koniec, e dysk X: moemy usun poleceniem subst X: /D. Nie powoduje to oczywicie utraty danych, które s bezpiecznie przechowywane w folderze dotychczas skojarzonym z napdem X:. Konsol natomiast zamkniemy poleceniem exit. Na listingu 1.1 przedstawiono wersj pliku console.bat uywan przez autora. Listing 1.1. console.bat path C:\Program Files\Java\jdk1.6.0 27\bin; %PATH% subst X: H:\!JAVA ZZ\Pliki X: cls call cmd c: subst X: /D
Dwa kocowe wiersze s wykonywane dopiero po zamkniciu konsoli poleceniem exit (nie naley zamyka okna konsoli w inny sposób). Na rysunku 1.1 widoczne jest rozwizanie zastosowane w konfiguracji skrótu na pulpicie.
2. JDK, Notatnik i klasyczny przykad „Hello World” Zadanie 2.1. Hello.java, Z02 1.java Kolejno postpowania bdzie nastpujca: 1. Przygotuj do pracy dysk X: (otwórz skrót z pulpitu). Dalej pracuj w konsoli
na dysku X:. 2. Poleceniem edytuj Hello utwórz plik tekstowy Hello.java (w Notatniku)
i przepisz podany kod. Zapisz tekst (Ctrl+S) i zamknij Notatnik (Alt+F4).
102
Programowanie w jzyku Java
Rysunek 1.1. Propozycja konfiguracji skrótu na pulpicie
public class Hello { public static void main(String args[]) { System.out.println("Hello World"); } }
3. Skompiluj kod ródowy poleceniem kompiluj Hello (stosujc plik wsadowy kompiluj.bat) lub javac Hello.java. Jeli kompilacja si nie powioda
(s komunikaty o bdach), wró do punktu 2. 4. Uruchom aplikacj poleceniem uruchom Hello (plik wsadowy uruchom.bat) lub java Hello. Pamitaj o wielkoci liter (Java rozrónia wielko liter — sowa: hello, Hello i HELLO s trzema rónymi identyfikatorami).
Jako parametr uruchomienia podajemy nazw klasy, a nie nazw pliku. Pierwsza aplikacja zostaa uruchomiona. Przedstawion tu procedur stosuj do dalszych zada. Zapamitaj równie kilka wanych informacji. Prosta aplikacja w jzyku Java skada si z jednej publicznej klasy. Nazw klasy rozpoczynamy zwykle od wielkiej litery. Jeli nazwa klasy skada si z kilku sów, to czymy je w jedno sowo, stosujc tzw. notacj wielbdzi (CamelCase), np.: MojaPierwszaKlasa. Klasa ta musi zawiera publiczn i statyczn metod main, od której rozpoczyna si wykonanie aplikacji. Nazwa pliku ródowego musi by zgodna (równie pod wzgldem wielkoci liter) z nazw klasy. Wymagane jest rozszerzenie .java, np. MojaPierwszaKlasa.java. Kompilujemy kod ródowy klasy, np. javac MojaPierwszaKlasa.java. Efektem kompilacji jest kod bajtowy (B-kod, betakod, ang. bytecode) zapisany w pliku MojaPierwszaKlasa.class. Aplikacj uruchamiamy, otwierajc wirtualn maszyn Javy (JVM) i przekazujc do interpretacji (jako parametr) nazw skompilowanej klasy, np. java MojaPierwszaKlasa.
Rozdzia 5. i Rozwizania zada
103
Umiesz ju przepisa kod, skompilowa plik ródowy i uruchomi aplikacj. Przeanalizujmy ten prosty przykad. Zacznijmy od budowy klasy. Kod klasy skada si ze sowa kluczowego class, identyfikatora (nazwy klasy) i ciaa klasy ujtej w nawiasy klamrowe {}, np. class Pusta { }. W naszym przypadku wystpuje jeszcze sowo kluczowe public, okrelajce dostp (publiczny) do klasy. W ciele klasy wystpuje publiczna i statyczna metoda main: public static void main(String args[]) { }
Sowo kluczowe public oznacza, e metoda main() jest widoczna dla wszystkich elementów programu. Metoda statyczna (sowo kluczowe static) jest dostpna bez koniecznoci tworzenia obiektu klasy. Przed nazw metody main wystpuje sowo kluczowe void, informujce, e metoda nie zwraca adnej wartoci (pusty typ wyniku). W nagówku metody main() konieczne jest zadeklarowanie tablicy argumentów String args[] lub String[] args (obie postacie deklaracji oznaczaj to samo). String jest nazw klasy (typu obiektowego) sucej do wykonywania operacji na acuchach znaków (tekstach), args jest identyfikatorem deklarowanego obiektu4, a symbol [] oznacza tablic zoon z kilku obiektów. Podczas uruchomienia aplikacji ta tablica jest wypeniana przez system parametrami wywoania. Szczegóy wkrótce. W tym przykadzie nie korzystamy z tablicy argumentów, ale taka deklaracja musi by w nagówku metody main(). W ciele metody wystpuje jeden wiersz, odpowiedzialny za wywietlenie tekstu Hello World w konsoli: System.out.println("Hello World");
W klasie System zdefiniowana jest statycznie zmienna obiektowa out. Metody tej zmiennej dziaaj na standardowym strumieniu wyjciowym. Uyta w przykadzie metoda println() wysya na standardowe wyjcie (konsol) dane przekazane jako parametr podczas wywoania metody i kod koca wiersza5. W tym przykadzie argumentem jest staa warto tekstowa, czyli litera acuchowy "Hello World".
Zadanie 2.2. Witam.java, Z02 2.java To kolejny przykad wykorzystania metody System.out.println opisanej w rozwizaniu zadania 2.1. Problem prawidowego wywietlania liter z polskimi znakami diakrytycznymi w konsoli omówiono, podajc wskazówk do zadania.
4
5
Ten identyfikator mona zmieni, ale nie ma potrzeby tego robi. Sowo args jest po prostu skrótem od sowa argumenty (ang. arguments). Parametr moe by wielkoci sta (literaem), zmienn dowolnego typu lub wyraeniem. Metoda println() wywoana bez parametru powoduje tylko przeniesienie kursora na pocztek nowej linii. Ist nieje te podobnie dziaajca metoda print(), która wypisuje informacj na standardowym wyjciu, ale nie przenosi kursora do nowego wiersza.
104
Programowanie w jzyku Java public class Witam { public static void main(String args[]) { System.out.println("Witaj, wiecie."); System.out.println("Ucz si programowa w jzyku Java."); } }
Zadanie 2.3. Adres.java, Z02 3.java W acuchu znaków umieszczono specjalny znak \n, powodujcy przejcie tekstu umieszczonego za znakiem do nowego wiersza. public class Adres { public static void main(String args[]) { /* Dane osoby i adres s zupenie fikcyjne */ System.out.println("Ewa Nowak\nul. Krótka 1\n11 111 Fikcja Dolna"); } }
W ten sposób w acuchu moemy umieci inne znaki specjalne: \b — backspace, \t — tabulacja, \r — powrót karetki, \" — cudzysów, \' — apostrof, \\ — lewy ukonik.
Zadanie 2.4. Etykieta.java, Z02 4.java public class Etykieta { public static void main(String args[]) { System.out.println("******* Programowanie *******"); System.out.println("* obiektowe w jzyku Java *"); System.out.println("* Jan Nowak *"); System.out.println("*****************************"); } }
3. Znaki, tablice znaków i klasa String Zadanie 3.1. Witaj.java, Z03 1.java Deklarujemy tablic znaków (char[]) o nazwie witaj. Rozmiar tablicy nie zosta ustalony. Poniewa czymy deklaracj z inicjowaniem elementów tablicy, to kompilator na tej podstawie obliczy rozmiar tablicy i wypeni j odpowiednimi wartociami. Zwrómy uwag na sposób zapisu znaków z uyciem apostrofów i zapamitajmy zasadnicz rónic: 'A' — znak, litera A; "A" — acuch znaków (jednoelementowy), zawierajcy jeden znak A. Jeli potrzebujemy wywietli wszystkie znaki zapisane w tablicy (w kolejnoci ich wystpowania), to moemy uy metody print lub println, przekazujc nazw tablicy jako parametr wywoania metody. public class Witaj { public static void main(String args[]) {
Rozdzia 5. i Rozwizania zada
105
char[] witaj = {'D', 'z', 'i', 'e', ' ', ' ', 'd', 'o', 'b', 'r', 'y'}; System.out.println(witaj); } }
Zadanie 3.2. Informatyka.java, Z03 2.java W dziaaniach zwizanych z przetwarzaniem tablic czsto wykorzystujemy instrukcje iteracyjne (ptle). Zawarto tablicy moemy wywietli, uywajc ptli typu for each (wprowadzonej do jzyka Java SE 5.0): for(typ zmiennej zmienna : kolekcja) instrukcja;
W powyszym zapisie for jest sowem kluczowym definiujcym ptl, identyfikator zmienna oznacza zmienn typu typ zmiennej zawartego w kolekcji, dwukropek (:) oddziela zmienn od identyfikatora kolekcji (wymaga tego skadnia ptli for each), kolekcja w tym przypadku oznacza nazw tablicy6. Identyfikator zmiennej i nazwa kolekcji ujte s w nawiasy ( ), natomiast za nawiasem znajduje si instrukcja do powtarzania. Instrukcja powtarzana jest tyle razy, ile elementów zawiera kolekcja; w kadym powtórzeniu cyklu warto zmiennej jest równa wartoci kolejnego elementu kolekcji. Naley doda, e ptla typu for each suy do odczytywania kolekcji i za porednictwem zmiennej nie moemy modyfikowa wartoci elementów kolekcji. Ptla for(char x : a) System.out.print(x); wywietli w konsoli po kolei wszystkie znaki zapisane w tablicy a. Oczywicie moemy z wartoci zmiennej x wykona inne, bardziej skomplikowane operacje ni tylko wywietlanie w konsoli. a) W ptli for(char znak : dane) ... pobieramy do zmiennej znak kolejne elementy z tablicy dane. Kady pobrany z tablicy znak wywietlamy w odrbnym wierszu konsoli System.out.println(znak). b) Pisanie tekstem rozstrzelonym (spacjowanie) polega na pisaniu tekstu znak
po znaku, oddzielajc kolejne znaki odstpami (spacjami). W ptli pobieramy z tablicy kolejne znaki i wywietlamy w konsoli System.out.print(znak); System.out.print(" ");. c) W klasie Character zdefiniowano statyczn metod toUpperCase()
zmieniajc ma liter na odpowiadajc jej wielk liter. Wykorzystujemy t metod do zamiany znaków odczytywanych z tablicy System.out.print(Character.toUpperCase(znak));. d) Pobrane z tablicy dane znaki (mae lub wielkie litery), zamieniamy na mae litery (Character.toLowerCase(znak)) i wywietlamy w konsoli. public class Informatyka { public static void main(String args[]) { char dane[] = {'I', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'y', 'k', 'a'}; /* Zadanie 3.2a */ System.out.println("Pionowo: ");
6
Dalej bd przedstawione inne kolekcje.
106
Programowanie w jzyku Java for(char znak : dane) System.out.println(znak); System.out.println(); /* Zadanie 3.2b */ System.out.print("Tekst rozstrzelony: "); for(char znak : dane) { System.out.print(znak); System.out.print(" "); } System.out.println(); /* Zadanie 3.2c */ System.out.print("Wielkie litery: "); for(char znak : dane) System.out.print(Character.toUpperCase(znak)); System.out.println(); /* Zadanie 3.2d */ System.out.print("Mae litery: "); for(char znak : dane) System.out.print(Character.toLowerCase(znak)); System.out.println(); } }
Metody toLowerCase() i toUpperCase() zmieniaj wycznie wielko liter, nie powoduj adnych zmian w pozostaych znakach.
Zadanie 3.3. Programowanie.java, Z03 3.java Stosujc podstawienie dane[0] = Character.toUpperCase(dane[0]);, zmienimy pierwszy znak zapisany w tablicy dane. Podobnie mona postpi z pozostaymi znakami. Indeksy znaków zapisanych w tablicy zmieniaj si w zakresie od 0 do wartoci o 1 mniejszej od rozmiaru tablicy. Dostp do wszystkich znaków w tablicy dane uzyskamy, stosujc ptl typu for: for(int i=0; i < dane.length; ++i) { // Tu wykonaj przeksztacenie zwizane z elementem dane[i]. }
Ptla for bdzie dalej omówiona dokadniej; na razie zapamitaj, e zmienna i typu cakowitego int bdzie w tym przypadku zmieniaa si od 0 (na pocztku inicjujemy zmienn int i=0;) do wartoci dane.length–1. Instrukcja zawarta w ciele ptli wykonuje si, gdy speniony jest warunek i < dane.length. Po kadym wykonaniu ptli warto zmiennej i jest zwikszana o 1 (operator inkrementacji ++i7). Ptla wykona si dokadnie tyle razy, ile elementów ma tablica dane, a zmienna i przyjmie kolejno wartoci indeksów wszystkich elementów tablicy. Sowo kluczowe int jest nazw typu do przechowywania liczb cakowitych w zakresie od –231 do 231–1. Konstrukcja int a; jest deklaracj zmiennej a typu int, natomiast int a = warto; deklaruje zmienn i inicjuje jej warto pocztkow (warto moe by literaem lub wyraeniem). 7
Zapis ++i jest równowany podstawieniu i = i+1.
Rozdzia 5. i Rozwizania zada
107
public class Programowanie { public static void main(String args[]) { char dane[] = {'p', 'r', 'o', 'g', 'r', 'a', 'm', 'o', 'w', 'a', 'n', 'i', 'e'}; System.out.print("Tablica znaków: "); System.out.println(dane); /* Zmiana pierwszej litery na wielk */ dane[0] = Character.toUpperCase(dane[0]); System.out.print("Pierwsza litera wielka: "); System.out.println(dane); /* Zmiana wszystkich liter na wielkie */ for(int i=0; i < dane.length; ++i) dane[i] = Character.toUpperCase(dane[i]); System.out.print("Wszystkie litery wielkie: "); System.out.println(dane); } }
Zadanie 3.4. Wspak1.java, Z03 4.java Do przegldania tablicy zastosujemy ptl for, w której nastpuje odliczanie w dó (od wartoci wikszych do mniejszych: for(int i=dane.length 1; i >= 0; i) { // Tu wykonamy przeksztacenie zwizane z elementem dane[i]. }
Na pocztku zmienn i inicjujemy wartoci równ indeksowi ostatniego elementu (rozmiar tablicy zmniejszony o 1 — int i=dane.length–1). Instrukcje s wykonywane, gdy i >= 0 (i jest wiksze lub równe 0). Po kadym wykonaniu instrukcji warto zmiennej i jest zmniejszana o 1 (dekrementacja ––i8). public class Wspak1 { public static void main(String args[]) { char dane[] = {'p', 'r', 'o', 'g', 'r', 'a', 'm', 'o', 'w', 'a', 'n', 'i', 'e'}; System.out.print("Normalna kolejno znaków: "); System.out.println(dane); System.out.print("Odwrotna kolejno znaków: "); for(int i = dane.length 1; i >= 0; i) System.out.print(dane[i]); System.out.println(); } }
Zadanie 3.5. Wspak2.java, Z03 5.java Do zamiany wartoci dwóch elementów uyjemy zmiennej pomocniczej wedug schematu: p = a; a = b; b = p; — spowoduje to wymian wartoci pomidzy zmiennymi a i b. Odwracanie tablicy znaków zrealizujemy, zamieniajc pierwszy znak z ostatnim, drugi z przedostatnim — i tak do chwili, gdy dojdziemy do rodka tablicy. W tym celu wykorzystamy nastpujce zmienne: i — indeks pierwszego znaku (indeks ten zwiksza 8
Zapis
i jest równowany podstawieniu i = i 1.
108
Programowanie w jzyku Java
si, przechodzc od pocztku (int i = 0) do rodka tablicy), j — indeks ostatniego znaku (indeks ten zmniejsza si, przechodzc od koca (int j = dane.length-1) do rodka tablicy), tmp — zmienna pomocnicza do zamiany wartoci dwóch elementów tablicy. Czynnoci zamiany elementów s powtarzane, gdy i < j. Na koniec kadego cyklu zwikszamy indeks i (++i) i zmniejszamy indeks j (--j), zbliajc si do rodka tablicy. public class Wspak2 { public static void main(String args[]) { char dane[] = {'p', 'r', 'o', 'g', 'r', 'a', 'm', 'o', 'w', 'a', 'n', 'i', 'e'}; System.out.print("Normalna kolejno znaków: "); System.out.println(dane); for(int i = 0, j = dane.length 1; i < j ; ++i, j) { char tmp = dane[i]; dane[i] = dane[j]; dane[j] = tmp; } System.out.print("Odwrotna kolejno znaków: "); System.out.println(dane); } }
Zadanie 3.6. DemoCharacter.java, Z03 6.java Pierwszy wiersz kodu import static java.lang.System.*; powoduje zaimportowanie do naszej klasy wszystkich elementów statycznych z klasy java.lang.System (w tym obiektu out). W dalszej czci kodu moemy posugiwa si tym obiektem bez podawania nazwy klasy, z której pochodzi. Zamiast odwoania System.out.println(...); wystarczy out.println(...);. Na pocztku umieszczono kilka informacji o metodzie digit (ang. digit — cyfra): out.println("Klasa: java.lang.Character"); — klasa Character znajduje si w pakiecie java.lang. out.println("Metoda statyczna: digit\n"); — omawiana metoda jest metod statyczn, nie potrzebujemy tworzy obiektu klasy Character,
aby skorzysta z tej metody. out.println("static int digit(int ch, int radix)"); — nagówek metody digit zawiera: sowo kluczowe static (metoda jest statyczna), typ zwracanej wartoci int i list parametrów wywoania metody (int ch, int radix). out.println("Returns the numeric value of the character ch in the specified radix."); — pierwsze zdanie z dokumentacji metody, informujce o dziaaniu metody. Metoda digit zwraca liczb bdc wartoci cyfry reprezentowanej przez znak ch w ukadzie pozycyjnym o okrelonej podstawie (radix).
Nastpnie zadeklarowano przykadow tablic znaków zawierajc znaki napisu Euro 2012 — char znak[] = {'E', 'u', 'r', 'o', ' ', '2', '0', '1', '2'};.
Rozdzia 5. i Rozwizania zada
109
Dziaanie metody pokazano w dwóch przypadkach, obliczajc wartoci znaków w tablicy jako cyfr ukadów dziesitkowego (radix = 10) oraz szesnastkowego (radix = 16). W ptli for pobieramy kolejne znaki z tablicy, wywietlamy w konsoli ich posta znakow i warto jako cyfry w okrelonym ukadzie liczbowym. Sprawdzamy cyfry ukadu dziesitkowego: for(char z : znak) out.println("Znak: "+z+"
Cyfra: "+Character.digit(z, 10));
Wynik -1 oznacza, e znak nie jest cyfr w tym ukadzie liczbowym. Warto znaku jako cyfry w ukadzie dziesitkowym (radix = 10) Znak: E Cyfra: 1 Znak: u Cyfra: 1 Znak: r Cyfra: 1 Znak: o Cyfra: 1 Znak: Cyfra: 1 Znak: 2 Cyfra: 2 Znak: 0 Cyfra: 0 Znak: 1 Cyfra: 1 Znak: 2 Cyfra: 2
Podobnie sprawdzimy cyfry w ukadzie szesnastkowym: for(char z : znak) out.println("Znak: "+z+"
Cyfra: "+Character.digit(z, 16));
Po wykonaniu kodu zauwaymy, e litera E jest cyfr w ukadzie szesnastkowym (warto dziesitna 14). Warto znaku jako cyfry w ukadzie szesnastkowym (radix = 16) Znak: E Cyfra: 14 Znak: u Cyfra: 1 Znak: r Cyfra: 1 Znak: o Cyfra: 1 Znak: Cyfra: 1 Znak: 2 Cyfra: 2 Znak: 0 Cyfra: 0 Znak: 1 Cyfra: 1 Znak: 2 Cyfra: 2
Zadanie 3.7. Cyfry.java, Z03 7.java Zgodnie z podan wskazówk odrzucamy najprostsze rozwizanie: char[] cyfry = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};. Wykorzystamy fakt, e kody cyfr dziesitnych (0123456789) s liczbami z zakresu od 48 do 57. Aby zamieni kod znaku (liczb cakowit) na odpowiadajcy mu znak, posuymy si rzutowaniem typów, np.: (char) 48 — liczb cakowit 48 rzutujemy na typ char i otrzymujemy znak '0'. public class Cyfry { public static void main(String args[]) { char[] cyfry = new char[10];
110
Programowanie w jzyku Java for(int i = 0; i < 10; ++i) cyfry[i] = (char)(i+48); System.out.print("Cyfry ukadu dziesitkowego: "); System.out.println(cyfry); } }
Ptl wypeniajc tablic moemy równie zapisa w postaci: for(int i = 48; i < 58; ++i) cyfry[i] = (char)i;
Zadanie 3.8. Cyfry16.java, Z03 8.java Zadanie to moemy rozwiza podobnie jak zadanie 3.7. Do zapisania liczby w ukadzie szesnastkowym potrzebujemy szesnastu cyfr — dziesi z nich to cyfry znane z ukadu dziesitkowego (0123456789 — znaki o kodach od 48 do 57), jako sze pozostaych cyfr wykorzystamy litery ABCDEF (znaki o kodach od 65 do 70). public class Cyfry16 { public static void main(String args[]) { char[] cyfry = new char[16]; for(int i = 0; i < 10; ++i) cyfry[i] = (char)(i+48); for(int i = 10; i < 16; ++i) cyfry[i] = (char)(i+55); System.out.print("Cyfry ukadu szesnastkowego: "); System.out.println(cyfry); } }
Do rozwizania zadania moemy wykorzysta statyczn metod forDigit (z dwoma parametrami int digit i int radix) z klasy Character, zamieniajc warto liczbow (parametr digit) na odpowiadajc jej cyfr (znak) w ukadzie liczbowym o podstawie radix. public class Cyfry16 { public static void main(String args[]) { char[] cyfry = new char[16]; for(int i = 0; i < 16; ++i) cyfry[i] = Character.forDigit(i, 16); System.out.print("Cyfry ukadu szesnastkowego: "); System.out.println(cyfry); } }
Metoda forDigit zwróci cyfry o wartoci wikszej od 9 jako mae litery (abcdef). Moemy przyj takie rozwizanie lub dodatkowo zamieni te znaki na wielkie litery (stosujc metod poznan w rozwizaniu zadania 3.2): for(int i = 0; i < 16; ++i) cyfry[i] = Character.toUpperCase(Character.forDigit(i, 16));
Rozdzia 5. i Rozwizania zada
111
4. Klasa String — operacje na tekstach Zadanie 4.1. TestString.java, Z04 1.java "Zadania z programowania." — acuch znaków stanowicy punkt wyjcia do dalszych
przeksztace. "Zadania z programowania.".charAt(0) — wyodrbnienie znaku o indeksie 0 (pierw-
szy znak acucha). "Zadania z programowania.".length() — dugo acucha (liczba znaków, w tym
przypadku 24). "Zadania z programowania.".charAt(23) — wyodrbnienie znaku o indeksie 23 (ostat-
ni znak acucha). "Zadania z programowania.".toUpperCase() — zamiana liter w acuchu na wielkie litery (oczywicie zwracana jest kopia acucha, na której dokonano zmian, orygina pozostaje nienaruszony). "Zadania z programowania.".toLowerCase() — zamiana liter w acuchu na mae li-
tery (jw.). "Zadania z programowania.".indexOf('z') — indeks pozycji pierwszego wystpienia znaku z. Jeli podany znak nie wystpuje w acuchu, to zwracana jest warto –1. "Zadania z programowania.".indexOf("prog") — indeks pozycji pierwszego wystpienia cigu "prog". Jeli podany cig nie wystpuje w acuchu, to zwracana jest warto –1. "Zadania z programowania.".replace('.', '?') — zwraca nowy cig, w którym wszystkie znaki kropki (.) zostan zastpione znakiem pytajnika (?). "Zadania z programowania.".replace("adania", "dania") — zastpienie wszystkich wystpie cigu "adania" cigiem "dania". "Zadania z programowania.".replaceAll("ania", "anka") — zastpienie wszystkich wystpie cigu "ania" cigiem "anka". "Zadania z programowania.".replaceFirst("ania", "anka") — zastpienie pierwszego wystpienia cigu "ania" cigiem "anka". "Zadania z programowania.".substring(10) — wyodrbnienie cigu od znaku o in-
deksie 10 do koca acucha wyjciowego. "Zadania z programowania.".substring(10, 17) — wyodrbnienie cigu od znaku o indeksie 10 do znaku stojcego przed znakiem o indeksie 17. Dugo wyodrbnionego acucha: 17–10 = 7 znaków.
112
Programowanie w jzyku Java "Zadania z programowania.".concat("\b z podpowiedziami.") — doczenie na kocu acucha "Zadania z programowania." cigu znaków "\b z podpowiedziami.". Pierwszy znak w doczanym cigu jest znakiem specjalnym \b (backspace) i spowo-
duje skasowanie ostatniego znaku (kropki) w acuchu wyjciowym. "Zadania z programowania."+"\b"+" z odpowiedziami." — zczenie trzech acuchów znaków w jeden acuch (operator +).
Zadanie 4.2. DemoString.java, Z04 2.java Tworzymy zmienn obiektow napis klasy String i inicjujemy j wartoci "Zadania z programowania.". String napis = "Zadania z programowania.";
W tej sytuacji przykad z listingu 4.1 wyglda tak: public class DemoString { public static void main(String args[]) { String napis = "Zadania z programowania."; System.out.println(napis); System.out.println(napis.charAt(0)); System.out.println(napis.length()); System.out.println(napis.charAt(napis.length() 1)); System.out.println(napis.toUpperCase()); System.out.println(napis.toLowerCase()); System.out.println(napis.indexOf('z')); System.out.println(napis.indexOf("prog")); char kropka = '.', pytajnik = '?'; System.out.println(napis.replace(kropka, pytajnik)); System.out.println(napis.replace("adania", "dania")); String str1 = "ania", str2 = "anka"; System.out.println(napis.replaceAll(str1, str2)); System.out.println(napis.replaceFirst(str1, str2)); System.out.println(napis.substring(10)); System.out.println(napis.substring(10, 17)); str1 = "\b z podpowiedziami."; System.out.println(napis.concat(str1)); System.out.println(napis+str1.substring(0, 4)+str1.substring(5)); } }
Dziaanie zastosowanych metod omówiono w rozwizaniu zadania 4.1.
Zadanie 4.3. WitajStr.java, Z04 3.java Tworzymy obiekt witaj klasy String zainicjowany wartoci "Dzie dobry". Metoda length zwraca rozmiar (dugo) acucha znaków. Znaki acucha s indeksowane (podobnie jak tablice) indeksami o wartociach od 0 do wartoci o 1 mniejszej od dugoci acucha. Znaki acucha o podanym indeksie udostpnia nam metoda charAt. W ptli for(int i = 0; i < witaj.length(); ++i)... uzyskamy dostp (po kolei) do wszystkich znaków acucha witaj.charAt(i). Znaki moemy w ten sposób wycznie odczytywa. Tak wanie rozwiemy czci a) i b) naszego zadania.
Rozdzia 5. i Rozwizania zada
113
public class WitajStr { public static void main(String args[]) { String witaj = "Dzie dobry"; /* Zadanie 4.3a */ System.out.println("Pionowo: "); for(int i = 0; i < witaj.length(); ++i) System.out.println(witaj.charAt(i)); System.out.println(); /* Zadanie 4.3b */ System.out.print("Tekst rozstrzelony: "); for(int i = 0; i < witaj.length(); ++i) System.out.print(witaj.charAt(i)+" "); System.out.println(); /* Zadanie 4.3c */ System.out.print("Wielkie litery: "+witaj.toUpperCase()); System.out.println(); /* Zadanie 4.3d */ System.out.print("Mae litery: "+witaj.toLowerCase()); System.out.println(); } }
W przypadku acucha znaków nie musimy zamienia odrbnie kadego znaku (mae litery na wielkie lub odwrotnie, wielkie na mae). Do rozwizania czci zadania zawartych w podpunktach c) i d) moemy wykorzysta metody toUpperCase lub toLowerCase zwracajce acuch (obiekt) zapisany odpowiednio wielkimi lub maymi literami. Jeli zamienimy acuch na tablic znaków, to moemy skorzysta z ptli typu for each (podajemy fragment kodu) i rozwiza zadanie w sposób znany z rozwizania zadania 3.2: /* Zadanie 4.3a */ System.out.println("Pionowo: "); for(char z : witaj.toCharArray()) System.out.println(z); System.out.println(); /* Zadanie 4.3b */ System.out.print("Tekst rozstrzelony: "); for(char z : witaj.toCharArray()) System.out.print(z+" "); System.out.println();
Zadanie 4.4. ProgramowanieStr.java, Z04 4.java, Z04 4a.java Obiekt klasy String nie jest modyfikowalny, czyli nie jest moliwe zmienianie w nim znaków, dodawanie do niego nowych znaków lub usuwanie z niego znaków istniejcych. Moemy natomiast zbudowa na jego podstawie nowy acuch speniajcy warunki zadania i przypisa go do tej samej referencji (zmiennej nazwa). Zbdny acuch zostanie usunity z pamici przez mechanizm garbage collection (ang. — czyszczenie pamici, usuwanie niepotrzebnych obiektów). Tworzymy acuch znaków String napis = "programowanie"; zawierajcy sowo programowanie zapisane maymi literami.
114
Programowanie w jzyku Java a) Z acucha napis pobieramy pierwszy znak napis.charAt(0), czyli znak p, i zamieniamy go na wielk liter Character.toUpperCase(napis.charAt(0)), otrzymujc znak P. Do tego znaku dodajemy podacuch acucha napis, od znaku o indeksie 1 do koca acucha napis.substring(1), czyli sowo rogramowanie. Operator konkatenacji (+) zamieni znak 'P' na acuch jednoelementowy "P" i poczy z acuchem "rogramowanie" w acuch "Programowanie": napis = Character.toUpperCase(napis.charAt(0))+napis.substring(1);
Mona to samo uzyska nieco inaczej: napis = (""+napis.charAt(0)).toUpperCase()+napis.substring(1);
W wyniku dodawania ""+napis.charAt(0) (pusty acuch "" czymy z pojedynczym znakiem 'p') otrzymujemy jednoelementowy acuch "p", który metoda toUpperCase zamienia na acuch "P". Nastpnie mamy znan ju operacj "P"+"rogramowanie", oczywicie zapisan w inny sposób. I jeszcze raz to samo, ale w innym zapisie (komentarz naley do Czytelnika): napis = napis.substring(0, 1).toUpperCase()+napis.substring(1);
b) Zamieniajc wszystkie litery na wielkie, wystarczy uy metody toUpperCase dla obiektu napis — napis = napis.toUpperCase();. public class ProgramowanieStr { public static void main(String args[]) { String napis = "programowanie"; System.out.print("a cuch znaków: "); System.out.println(napis); /* Zmiana pierwszej litery na wielk */ napis = Character.toUpperCase(napis.charAt(0))+ napis.substring(1); System.out.print("Pierwsza litera wielka: "); System.out.println(napis); /* Zmiana wszystkich liter na wielkie */ napis = napis.toUpperCase(); System.out.print("Wszystkie litery wielkie: "); System.out.println(napis); } }
Powracajc do podpunktu a) zadania, moemy zaproponowa takie rozwizanie: String napis = "programowanie"; char[] znaki = napis.toCharArray(); znaki[0] = Character.toUpperCase(znaki[0]); napis = String.valueOf(znaki);
Analiz kodu zostawiamy Czytelnikowi.
Zadanie 4.5. WspakStr1.java, Z04 5.java Podobnie jak w rozwizaniu zadania 3.4, wykorzystamy ptl for ze zmniejszaniem wartoci zmiennej sterujcej.
Rozdzia 5. i Rozwizania zada
115
public class WspakStr1 { public static void main(String args[]) { String napis = "programowanie"; System.out.print("Normalna kolejno znaków: "); System.out.println(napis); System.out.print("Odwrotna kolejno znaków: "); for(int i = napis.length() 1; i >= 0 ; i) System.out.print(napis.charAt(i)); System.out.println(); } }
Porównajmy fragment powyszego kodu z fragmentem rozwizania zadania 3.4: for(int i = dane.length 1; i >= 0; i) System.out.print(dane[i]);
Obiekt napis klasy String ma metod length() zwracajc liczb znaków w acuchu, natomiast obiekt dane typu tablicowego (char[]) ma pole length zawierajce liczb elementów tablicy (w tym przypadku liczb znaków). Ponadto inny jest sposób odczytywania znaków o podanym indeksie.
Zadanie 4.6. WspakStr2.java, Z04 6.java Zadanie to moemy rozwiza w trzech krokach: zamieni acuch znaków na tablic znaków, odwróci kolejno znaków w tablicy (zob. zadanie 3.5), zbudowa acuch znaków na podstawie odwróconej tablicy. public class WspakStr2 { public static void main(String args[]) { String napis = "programowanie"; System.out.print("Normalna kolejno znaków: "); System.out.println(napis); /* Zamiana acucha na tablic znaków */ char[] dane = napis.toCharArray(); /* Odwracanie tablicy znaków. */ for(int i = 0, j = dane.length 1; i < j ; i++, j char tmp = dane[i]; dane[i] = dane[j]; dane[j] = tmp; } /* Zamiana tablicy znaków na acuch */ napis = new String(dane); System.out.print("Odwrotna kolejno znaków: "); System.out.println(napis); } }
) {
Do utworzenia acucha znaków na podstawie odwróconej tablicy wykorzystalimy konstruktor (napis = new String(dane)). Moemy zastosowa metod statyczn valueOf z klasy String (napis = String.valueOf(dane)).
116
Programowanie w jzyku Java
Zadanie 4.7. CyfryStr.java, Z04 7.java Odrzucilimy proste rozwizanie String cyfry = "0123456789";. Moemy zbudowa tablic znaków zawierajc cyfry (zob. rozwizanie zadania 3.7) i nastpnie zbudowa na tej podstawie acuch znaków: String cyfry = new String(tablica). Poniewa zadanie ma bardziej charakter poznawczy ni praktyczny, proponujemy modyfikacj rozwizania zadania 3.7 w nastpujcy sposób: public class CyfryStr { public static void main(String args[]) { String cyfry = ""; for(int i = 0; i < 10; ++i) cyfry += (char)(i+48); System.out.print("Cyfry ukadu dziesitkowego: "); System.out.println(cyfry); } }
Zwrómy uwag na operator += (podstawianie z dodawaniem — w tym przypadku dotyczce dodawania acuchów znaków), który skraca zapis wyraenia. Zamiast cyfry = cyfry+(char)(i+48) piszemy krócej: cyfry += (char)(i+48). Naley doda, e w tym przykadzie do acucha znaków dodajemy jeden znak (konwersja znaku na acuch nastpuje automatycznie w czasie wykonywania tej operacji). Zastosowane tutaj dodawanie acuchów jest przemienne, wic poprawny bdzie zapis wyraenia w postaci cyfry = (char)(i+48)+cyfry (nie mamy moliwoci skrócenia wyraenia za pomoc operatora +=). Jaki bdzie efekt, Czytelnik moe sprawdzi sam. Takiego zastosowania klasy String nie naley poleca . Kade dodawanie pojedynczego znaku (lub innego acucha) powoduje tworzenie nowego acucha z wynikiem (na szczcie nie musimy si troszczy o ich usuwanie). Póniej poznasz klasy StringBuffer i StringBuilder lepiej nadajce si do rozwizywania podobnych zada.
Zadanie 4.8. CyfryStr16.java, Z04 8.java Do zbudowania acucha cyfr szesnastkowych wykorzystamy statyczn metod forDigit z klasy Character. public class CyfryStr16 { public static void main(String args[]) { String cyfry = ""; for(int i = 0; i < 16; ++i) cyfry += Character.forDigit(i, 16); System.out.print("Cyfry ukadu szesnastkowego: "); cyfry = cyfry.toUpperCase(); System.out.println(cyfry); } }
Uwaga zamieszczona w rozwizaniu zadania 4.7 pozostaje aktualna. Zamian maych liter na wielkie moemy wykona równie podczas tworzenia acucha cyfry (w ptli): cyfry += Character.toUpperCase(Character.forDigit(i, 16));
Rozdzia 5. i Rozwizania zada
117
Moemy równie skopiowa kod rozwizania zadania 3.8 i uzupeni go o jedn linijk kodu String cyfryHex = String.valueOf(cyfry); lub String cyfryHex = new String(cyfry);.
5. Tablica argumentów aplikacji Zadanie 5.1. Argumenty.java, Z05 1.java Po uruchomieniu aplikacji poleceniem java Argumenty parametr1 parametr2 ... parametrN system operacyjny przekazuje podane argumenty do aplikacji w postaci tablicy. Deklaracj tej tablicy obowizkowo umieszczamy w nagówku metody main. Do przegldania tablicy argumentów moemy zastosowa ptl typu for each. public class Argumenty { public static void main(String args[]) { System.out.println("Liczba argumentów "+args.length); /* Lista argumentów - ptla typu for each */ for(String argument: args) System.out.println(argument); } }
W Javie kada tablica jest obiektem, którego waciwo length zawiera liczb elementów tablicy. Zatem pole args.length zawiera liczb przekazanych argumentów. Argumenty w programie s dostpne przy uyciu indeksów od 0 do args.length–1: args[0], args[1],…, args[N–1], gdzie N oznacza liczb argumentów. Do przegldania listy argumentów moemy zastosowa ptl typu for. /* Lista argumentów - ptla typu for */ for(int i = 0; i < args.length; ++i) System.out.println(args[i]);
Zadanie 5.2. Osoba.java, Z05 2.java Uruchamiamy w konsoli program poleceniem java Osoba Maria Kowalska. System operacyjny przekae do tablicy argumentów dwa parametry (imi i nazwisko). W tablicy argumentów mamy zatem args[0] = "Maria" i args[1] = "Kowalska". Zakadajc (zgodnie z treci zadania), e uytkownik moe niedokadnie wprowadzi wielko liter, musimy dokona odpowiednich korekt danych przed ich wywietlaniem. Nazwisko: Kowalska — rozdzielamy args[1] na dwie czci: pierwszy znak i reszta
acucha; pierwszy znak zamienimy na wielk liter, a reszt acucha wywietlimy maymi literami: System.out.println(args[1].substring(0, 1).toUpperCase() +args[1].substring(1).toLowerCase());
Imi: Maria — rozdzielamy args[0] na dwie czci: pierwszy znak i reszta acucha;
pierwszy znak zamienimy na wielk liter, a reszt acucha wywietlimy maymi literami:
118
Programowanie w jzyku Java System.out.println(Character.toUpperCase(args[0].charAt(0)) +args[0].substring(1).toLowerCase());
Nazwisko i imi: KOWALSKA Maria — nazwisko wywietlamy wielkimi literami (args[1]. toUpperCase()), imi tak jak w poprzednim punkcie. Inicjay: MK — wywietlamy pierwsze litery imienia i nazwiska: System.out.print(Character.toUpperCase(args[0].charAt(0))); System.out.println(Character.toUpperCase(args[1].charAt(0)));
Login: KOmar — login budujemy z dwóch pocztkowych liter nazwiska, zapisanych wielkimi literami (args[1].substring(0, 2).toUpperCase()) i trzech pocztkowych liter imienia zapisanych maymi literami (args[0].substring(0, 3).toLowerCase()). import static java.lang.System.out; public class Osoba { public static void main(String args[]) { out.print("Nazwisko: "); out.println(args[1].substring(0, 1).toUpperCase()+ args[1].substring(1).toLowerCase()); out.print("Imi: "); out.println(Character.toUpperCase(args[0].charAt(0))+ args[0].substring(1).toLowerCase()); out.print("Nazwisko i imi: "+args[1].toUpperCase()+" "); out.println(Character.toUpperCase(args[0].charAt(0))+ args[0].substring(1).toLowerCase()); out.print("Inicjay: "); out.print(Character.toUpperCase(args[0].charAt(0))); out.println(Character.toUpperCase(args[1].charAt(0))); out.print("Login: "); out.print(args[1].substring(0, 2).toUpperCase()); out.println(args[0].substring(0, 3).toLowerCase()); } }
Zwrómy uwag na skrócenie wierszy programu poprzez import statycznego obiektu out z klasy System i pomijanie nazwy klasy w operacjach wyjcia. W przykadzie pokazano równie dwa sposoby zamienienia pierwszego znaku acucha na wielk liter: str.toUpperCase().charAt(0) — utworzono acuch zapisany wielkimi literami i pobrano pierwszy znak, Character.toUpperCase(str.charAt(0)) — pobrano pierwszy znak acucha str i zamieniono na wielk liter. W podanym rozwizaniu nie zastosowano adnych dodatkowych zmiennych acuchowych. Uycie pomocniczych zmiennych mogoby zmniejszy liczb wykonywanych operacji na acuchach znaków. Pozostawimy to wiczenie do wykonania Czytelnikowi.
Zadanie 5.3. ArgsWspak.java, Z05 3.java Wywietlanie tablicy argumentów w odwrotnej kolejnoci moemy zrealizowa w ptli for z odliczaniem w dó, od ostatniego do pierwszego elementu.
Rozdzia 5. i Rozwizania zada
119
public class ArgsWspak { public static void main(String args[]) { for(int i = args.length 1; i >= 0; i) System.out.print(args[i]+" "); System.out.println("\b"); } }
Do kadego argumentu dodawany jest znak odstpu. Za ostatnim argumentem ten znak jest niepotrzebny (zreszt jest te niewidoczny, ale czasem mógby przeszkadza), wic kasujemy ten odstp przy uyciu specjalnego znaku '\b' (ang. backspace).
Zadanie 5.4. ArgWspak.java, Z05 4.java W ptli zewntrznej przegldamy zawarto tablicy argumentów, a w ptli wewntrznej wywietlamy argument w odwrotnej kolejnoci (wspak). public class ArgWspak { public static void main(String args[]) { /* Przegldanie tablicy argumentów - ptla zewntrzna. */ for(String argument : args) { /* Wywietlanie argumentu wspak */ for(int i = argument.length() 1; i >= 0; i) System.out.print(argument.charAt(i)); /* Przejcie do nowego wiersza */ System.out.println(); } } }
Zadanie 5.5. EtykietaArg.java, Z05 5.java Podczas wywoania programu podajemy imi i nazwisko jako argumenty. Do trzecie*";) musimy go wiersza etykiety (String wiersz = "* wstawi imi i nazwisko (String tekst = args[0]+" "+args[1];). Najpierw obliczamy rónic dugoci tych napisów int znaki = wiersz.length()-tekst.length();. Z acucha wiersz bierzemy pocztek, poow wyliczonej liczby znaków (wiersz. substring(0, znaki/2)). Do tego dodajemy imi i nazwisko (tekst) i na koniec dopisujemy reszt znaków, z koca acucha wiersz (wiersz.substring(wiersz.length() -znaki+znaki/2)). public class EtykietaArg { public static void main(String args[]) { /* Wypiszemy pierwszy i drugi wiersz etykiety. */ System.out.println("******* Programowanie *******"); System.out.println("* obiektowe w jzyku Java *"); /* Budujemy trzeci wiersz etykiety. Do tego wiersza musimy wstawi imi i nazwisko. */ String wiersz = "* *"; String tekst = args[0]+" "+args[1]; /* Obliczymy, ile znaków z oryginalnego wiersza naley pozostawi . */ int znaki = wiersz.length() tekst.length();
120
Programowanie w jzyku Java /* Poow pozostawionych znaków (pocztek wiersza) wstawimy przed tekstem. */ String tmp = wiersz.substring(0, znaki/2)+tekst; /* Reszt znaków (koniec wiersza) dopiszemy po tekcie. */ tmp += wiersz.substring(wiersz.length() znaki+znaki/2); /* Wypisujemy trzeci wiersz. */ System.out.println(tmp); /* Pozosta do wypisania ostatni wiersz etykiety. */ System.out.println("*****************************"); } }
Wystpujce w obliczeniach dzielenie jest dzieleniem cakowitym, co oznacza, e nie zawsze wyraenie znaki–znaki/2 ma tak sam warto jak wyraenie znaki/2. Nieparzysta liczba znaków nie moe by rozdzielona równomiernie przed tekstem i za tekstem. W takim przypadku na koniec zostawiamy o jeden znak wicej.
6. Prawda czy fasz — logiczny typ danych Zadanie 6.1. OperatoryLogiczne.java, Z06 1.java Tworzymy tablic bool zawierajc dwa elementy false i true typu boolean. W ptli for(boolean p: bool) {...} zmienna logiczna p bdzie przyjmowaa kolejno wartoci false i true. Dziki temu bdziemy mogli utworzy tabelk negacji i testowa prawa logiczne z jednym zdaniem p. Zagniedajc ptle for(boolean p: bool) for(boolean q: bool) {...}, otrzymamy par zmiennych logicznych p i q, przyjmujcych kolejno wartoci: (false, false), (false, true), (true, false) i (true, true). Pozwoli nam to na utworzenie tabelek koniunkcji, alternatywy i innych funktorów logicznych dwuargumentowych oraz testowanie praw logicznych z dwoma zdaniami logicznymi p i q. Powysze uwagi zostan wykorzystane w rozwizaniach zada 6.1, 6.2, 6.3, 6.4, 6.5 i 6.6 oraz innych podobnych. Do sformatowania (w kolumnach) wyników operacji logicznych uyjemy znaku tabulatora '\t' wewntrz acuchów tworzcych nagówki tabelek (aby uproci kod, nie rysujemy linii, pozostawiajc to Czytelnikowi) i acucha "\t" zawierajcego znak tabulatora, czonego z wartociami wywietlanych zmiennych, np. p+"\t"+!p. W zadaniu wykorzystujemy operator negacji (!), alternatywy (|) i koniunkcji (&). public class OperatoryLogiczne { public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Operator negacji (NOT)
!");
Rozdzia 5. i Rozwizania zada
121
System.out.println(" p\t !p"); for(boolean p: bool) System.out.println(p+"\t"+!p); System.out.println(); System.out.println("Operator koniunkcji (AND) & lub &&"); System.out.println(" p\t q\tp & q"); for(boolean p: bool) for(boolean q: bool) System.out.println(p+"\t"+q+"\t"+(p & q)); System.out.println(); System.out.println("Operator alternatywy (OR) | lub ||"); System.out.println(" p\t q\tp | q"); for(boolean p: bool) for(boolean q: bool) System.out.println(p+"\t"+q+"\t"+(p | q)); System.out.println(); } }
Operatory & i | s wykorzystywane równie do przeprowadzania operacji bitowych na binarnej reprezentacji danych. Poniewa true odpowiada liczbie 1, a false liczbie 0 (w reprezentacji wewntrznej), to obliczenia wykonane na wartociach logicznych daj waciwy wynik. Operatory && i || su wycznie do dziaa na wartociach logicznych. S nazywane szybkimi. Od operatorów & i | róni si sposobem wyliczania wartoci. Aby alternatywa dwóch wyrae bya prawdziwa, wystarczy, e jeden z operandów alternatywy jest prawdziwy. Jeli pierwszy operand alternatywy ma warto true, to wiadomo, e alternatywa jest prawdziwa (wartoci drugiego operandu nie musimy oblicza ). W przypadku koniunkcji — jeli pierwszy operand ma warto false, to cae wyraenie ma warto false.
Zadanie 6.2. PrawaLogiczne.java, Z06 2.java Badane prawa s zdaniami logicznymi zbudowanymi ze zdania p i poznanych w zadaniu 6.1 operatorów logicznych. Wartoci zdania p pobieramy z tablicy bool i budujemy odpowiednie wyraenia logiczne: p || !p — prawo wyczonego rodka, !(p && !p) — prawo niesprzecznoci, !(!p) == p) — prawo podwójnego przeczenia. W ostatnim przypadku jako operator równowanoci wykorzystano operator porównania ==, który zwraca warto true dla pary zda równowanych (false == false, true == true) i warto false dla zda nierównowanych (false == true, true == false). public class PrawaLogiczne { public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Prawo wyczonego rodka p || !p"); System.out.println(" p\t !p\tp || !p"); for(boolean p: bool) System.out.println(p+"\t"+!p+"\t"+(p || !p)); System.out.println();
122
Programowanie w jzyku Java System.out.println("Prawo niesprzecznoci !(p && !p)"); System.out.println(" p\t !p\tp && !p\t!(p && !p)"); for(boolean p: bool) System.out.println(p+"\t"+!p+"\t"+(p && !p)+"\t"+!(p && !p)); System.out.println(); System.out.println("Prawo podwójnego przeczenia !(!p) == p)"); System.out.println(" p\t !p\t!(!p)\t!(!p) == p)"); for(boolean p: bool) System.out.println(p+"\t"+!p+"\t"+!(!p)+"\t"+(!(!p) == p)); System.out.println(); } }
Zadanie 6.3. PrawaDeMorgana.java, Z06 3.java Stosujc tablic bool i zagniedone ptle (zob. komentarz w rozwizaniu zadania 6.1), moemy zbada prawa De Morgana. W dwóch pocztkowych kolumnach umieszczamy wszystkie moliwe wartoci dla dwóch zda logicznych ( p i q). W kolejnych umieszczamy wartoci porednich wyników, a w ostatniej kolumnie warto caego zdania (kompletne wyraenie). Uzyskane w ostatniej kolumnie wartoci true wiadcz, e to wyraenie jest prawem logicznym. public class PrawaDeMorgana { public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Zaprzeczenie koniunkcji jest równowane alternatywie zaprzecze "); System.out.println("p\tq\tp&&q\t!(p&&q)\t!p\t!q\t!p||!q\t!(p&&q) (!p||!q)"); for(boolean p: bool) for(boolean q: bool) { System.out.print(p+"\t"+q+"\t"+(p&&q)+"\t"+!(p&&q)); System.out.print("\t"+!p+"\t"+!q+"\t"+(!p||!q)); System.out.println("\t"+(!(p&&q)==(!p||!q))); } System.out.println("\n"); System.out.println("Zaprzeczenie alternatywy jest równowane koniunkcji zaprzecze "); System.out.println("p\tq\tp||q\t!(p||q)\t!p\t!q\t!p&&!q\t!(p||q) (!p&&!q)"); for(boolean p: bool) for(boolean q: bool) { System.out.print(p+"\t"+q+"\t"+(p||q)+"\t"+!(p||q)); System.out.print("\t"+!p+"\t"+!q+"\t"+(!p&&!q)); System.out.println("\t"+(!(p||q)==(!p&&!q))); } System.out.println("\n"); } }
Zadanie 6.4. Implikacja.java, Z06 4.java, Z06 4a.java Wykorzystujc rozwizanie zadania 6.2, uwagi z rozwizania zadania 6.1 oraz podan wskazówk, utworzymy nastpujc aplikacj:
Rozdzia 5. i Rozwizania zada
123
public class Implikacja { public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Implikacja jeeli p, to q"); System.out.println("p\tq\tp=>q"); for(boolean p: bool) for(boolean q: bool) System.out.println(p+"\t"+q+"\t"+ (Boolean.valueOf(p).compareTo(q) < 1)); System.out.println(); } }
Moemy zdefiniowa wasn metod statyczn realizujc zadania operatora implikacji (proponujemy nazw impl). Wicej szczegóów o definiowaniu metod poznasz dalej. static boolean impl(boolean p, boolean q) { return (Boolean.valueOf(p).compareTo(q) < 1)); }
Po takiej zmianie otrzymamy nastpujcy kod: public class Implikacja { static boolean impl(boolean p, boolean q) { return (Boolean.valueOf(p).compareTo(q) < 1); } public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Implikacja jeeli p, to q"); System.out.println("p\tq\tp=>q"); for(boolean p: bool) for(boolean q: bool) System.out.println(p+"\t"+q+"\t"+ impl(p, q)); System.out.println(); } }
Zadanie 6.5. Xor.java, Z06 5.java Alternatywa wykluczajca (p albo q) realizowana jest przez operator XOR (^) — alternatywa wykluczajca (ang. exclusive or). Moemy równie skorzysta z operatora nie jest równe (!=), poniewa alternatywa wykluczajca jest prawdziwa, gdy jedno ze zda jest prawdziwe, a drugie faszywe, czyli gdy ich wartoci logiczne nie s równe. W rozwizaniu zadania pokaemy i porównamy dziaanie operatora XOR (^) oraz operatora nie jest równe (!=) dla wartoci logicznych. public class Xor { public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Operator alternatywy wykluczajcej (XOR) ^"); System.out.println(" p\t q\tp ^ q"); for(boolean p: bool)
124
Programowanie w jzyku Java for(boolean q: bool) System.out.println(p+"\t"+q+"\t"+(p ^ q)); System.out.println(); System.out.println("Operator nie jest równe !="); System.out.println(" p\t q\tp != q"); for(boolean p: bool) for(boolean q: bool) System.out.println(p+"\t"+q+"\t"+(p != q)); System.out.println(); } }
Zadanie 6.6. Z06 6a.java, Z06 6b.java, Z06 6b.java, Z06 6d.java, Z06 6e.java W prawach dowodzonych w podpunktach a), b) i c) mamy prawa logiczne z trzema zdaniami logicznymi p, q i r. Uyjemy trzech zagniedonych ptli for i tablicy bool do wygenerowania wszystkich moliwych trójek wartoci logicznych dla zda logicznych p, q i r. Prawa dowodzone w podpunktach d) i e) zawieraj tylko dwa zdania logiczne p i q. W zadaniach a), d) i e) wystpuje implikacja. Skorzystamy z metody impl wprowadzonej w rozwizaniu zadania 6.4. W tabelach wprowadzono dodatkowe oznaczenia A, B, C i D, skracajce opis nagówka tabeli. a) Prawo przechodnioci implikacji
> p q q r @ p r .
public class PrawoLogiczneA { static boolean impl(boolean p, boolean q) { return (Boolean.valueOf(p).compareTo(q) < 1); } public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Prawo przechodnioci implikacji"); System.out.println("p\tq\tr\tp=>q\tq=>r\tA & B\tp=>r\tC=>D"); System.out.println("\t\t\t(A)\t(B)\t(C)\t(D)"); for(boolean p: bool) for(boolean q: bool) for(boolean r: bool) { System.out.print(p+"\t"+q+"\t"+r); System.out.print("\t"+impl(p, q)+"\t"+impl(q,r)); System.out.print("\t"+(impl(p, q)&impl(q, r))); System.out.print("\t"+impl(p,r)+"\t"); System.out.println(impl(impl(p, q)&impl(q, r), impl(p,r))); } System.out.println(); } }
b) Prawo rozdzielnoci alternatywy wzgldem koniunkcji > p q r @ > p q p r @ . W celu uproszczenia zapisu wprowadzono dodatkowe zmienne a, b, c, d i e typu boolean. public class PrawoLogiczneB { public static void main(String args[]) {
Rozdzia 5. i Rozwizania zada boolean[] bool = {false, true}; System.out.println("Prawo rozdzielnoci alternatywy wzgldem koniunkcji\n"); System.out.println("p\tq\tr\tq&r\tp|A\tp|q\tp|r\tC&D\tBE "); System.out.println("\t\t\t(A)\t(B)\t(C)\t(D)\t(E)"); for(boolean p: bool) for(boolean q: bool) for(boolean r: bool) { System.out.print(p+"\t"+q+"\t"+r); boolean a = q&r; boolean b = p|a; boolean c = p|q; boolean d = p|r; boolean e = c&d; System.out.print("\t"+a+"\t"+b+"\t"+c+"\t"+d+"\t"+e+"\t"); System.out.println(b == e); } System.out.println(); } }
c) Prawo rozdzielnoci koniunkcji wzgldem alternatywy > p q r @ > p q p r @ . Podobnie jak w podpunkcie b),
w celu uproszczenia zapisu wprowadzono dodatkowe zmienne a, b, c, d i e typu boolean. public class PrawoLogiczneC { public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Prawo rozdzielnoci koniunkcji wzgldem alternatywy\n"); System.out.println("p\tq\tr\tq|r\tp&A\tp&q\tp&r\tC|D\tBE"); System.out.println("\t\t\t(A)\t(B)\t(C)\t(D)\t(E)"); for(boolean p: bool) for(boolean q: bool) for(boolean r: bool) { System.out.print(p+"\t"+q+"\t"+r); boolean a = q|r; boolean b = p&a; boolean c = p&q; boolean d = p&r; boolean e = c|d; System.out.print("\t"+a+"\t"+b+"\t"+c+"\t"+d+"\t"+e+"\t"); System.out.println(b == e); } System.out.println(); } }
d) Prawo odrywania
> p q q@ q .
Zbudujemy dodatkow klas Impl zawierajc definicj metody impl zbudowanej w rozwizaniu zadania 6.4. W pliku Impl.java wpisujemy kod: public class Impl { static boolean impl(boolean p, boolean q) { return (Boolean.valueOf(p).compareTo(q) < 1); } }
125
126
Programowanie w jzyku Java
Po skompilowaniu otrzymamy plik Impl.class. Jeli ten plik umiecimy w biecym folderze, to metoda statyczna impl bdzie dostpna dla wszystkich klas znajdujcych si w tym samym folderze, czyli w tzw. pakiecie domylnym. Jest to w tym zbiorze zada pierwszy przykad klasy niezawierajcej metody main(), czyli niebdcej aplikacj. Metod bdziemy wywoywa z innych klas, np. Impl.impl(p, q). public class PrawoLogiczneD { public static void main(String args[]) { boolean[] bool = {false, true}; System.out.println("Prawo odrywania [(p => q) & q] => q\n"); System.out.println("p\tq\tp=>q\tA & q\tB=>q"); System.out.println("\t\t(A)\t(B)"); for(boolean p: bool) for(boolean q: bool) { boolean a = Impl.impl(p, q); boolean b = a & q; System.out.print(p+"\t"+q+"\t"+a+"\t"+b+"\t"); System.out.println(Impl.impl(b, q)); } System.out.println(); } }
e) Prawo eliminacji implikacji p q p q . Podobnie jak w punkcie d), skorzystamy z metody impl (zastpujcej operator implementacji) zdefiniowanej w klasie Impl. public class PrawoLogiczneE { public static void main(String args[]) { boolean[] bool = {false, true}; System.out.print("Prawo eliminacji implikacji "); System.out.println("(p => q) (!p|q)\n"); System.out.println("p\tq\tp=>q\t!p\t!p|q\tAB"); System.out.println("\t\t(A)\t\t(B)"); for(boolean p: bool) for(boolean q: bool) { boolean a = Impl.impl(p, q); boolean b = !p | q; System.out.print(p+"\t"+q+"\t"+a+"\t"+(!p)+"\t"+b+"\t"); System.out.println(a == b); } System.out.println(); } }
Zadanie 6.7. StringIsEmpty.java, Z06 7.java Metoda isEmpty zwraca warto true, gdy acuch nie zawiera ani jednego znaku (jest pusty), i warto false, gdy acuch zawiera co najmniej jeden znak. public class StringIsEmpty { public static void main(String[] args) { String str1 = ""; System.out.println("String: "+str1); System.out.println("Dugo a cucha: "+str1.length()); System.out.println("Czy string jest pusty? "+str1.isEmpty()); str1 = "Krótki tekst...";
Rozdzia 5. i Rozwizania zada
127
System.out.println("String: "+str1); System.out.println("Dugo a cucha: "+str1.length()); System.out.println("Czy string jest pusty? "+str1.isEmpty()); } }
Zadanie 6.8. TestChar.java, Z06 8.java a) Cig skada si z 7 znaków, s to: wielka litera A, tzw. spacja nierozdzielajca (kod dziesitny 160, ósemkowy \240), maa litera b, cyfra 3, znak &, cyfra 4
i odstp (spacja — kod dziesitny 32, biay znak). Program testujcy wywietla znaki wystpujce w acuchu, a nastpnie tworzy tabel z wynikami testów z uyciem metod isDigit(), isLetter(), isLetterOrDigit(), isLowerCase(), isSpaceChar(), isUpperCase() i isWhiteSpace(). W kadej kolumnie znajduj si znak, kod znaku i wyniki testu dla tego znaku. public class TestChar { public static void main(String[] args) { String str = "A\240b3&4\040"; // podpunkt a) System.out.println("Znaki: "+str); char[] znaki = str.toCharArray(); System.out.print("Znak "); for(char z : znaki) System.out.print("\t"+z); System.out.println(); System.out.print("Kod znaku "); for(char z : znaki) System.out.print("\t"+(int)z); System.out.println(); System.out.print("isDigit() "); for(char z : znaki) System.out.print("\t"+Character.isDigit(z)); System.out.println(); System.out.print("isLetter() "); for(char z : znaki) System.out.print("\t"+Character.isLetter(z)); System.out.println(); System.out.print("isLetterOrDigit()"); for(char z : znaki) System.out.print("\t"+Character.isLetterOrDigit(z)); System.out.println(); System.out.print("isLowerCase() "); for(char z : znaki) System.out.print("\t"+Character.isLowerCase(z)); System.out.println(); System.out.print("isSpaceChar() "); for(char z : znaki) System.out.print("\t"+Character.isSpaceChar(z)); System.out.println(); System.out.print("isUpperCase() "); for(char z : znaki) System.out.print("\t"+Character.isUpperCase(z)); System.out.println(); System.out.print("isWhitespace() ");
128
Programowanie w jzyku Java for(char z : znaki) System.out.print("\t"+Character.isWhitespace(z)); System.out.println(); } }
Po uruchomieniu programu uzyskamy wynik: Znaki: A b3&4 Znak Kod znaku isDigit() isLetter() isLetterOrDigit() isLowerCase() isSpaceChar() isUpperCase() isWhitespace()
A 65 false true true false false true false
160 false false false false true false false
b 98 false true true true false false false
3 51 true false true false false false false
& 38 false false false false false false false
4 52 true false true false false false false
32 false false false false true false true
b) Cig skada si z 7 znaków, s to: wielka litera , maa litera o, maa litera , znak podkrelenia , cyfra 0, znak + i znak tabulatora (\t — kod dziesitny 9). W kodzie programu TestChar zmieniamy jeden wiersz: String str = "o 4 -\t";. Dla tego acucha otrzymamy: Znaki: o 0+ Znak Kod znaku isDigit() isLetter() isLetterOrDigit() isLowerCase() isSpaceChar() isUpperCase() isWhitespace()
321 false true true false false true false
o 111 false true true true false false false
347 false true true true false false false
95 false false false false false false false
0 48 true false true false false false false
+ 43 false false false false false false false
Prezentowane znaki s znakami Unicode, co wyra nie wida w przypadku polskich znaków i (kody wiksze od 255, dwubajtowe). c) Cig skada si z 7 znaków, s to: znak #, znak cudzysowu " (znak specjalny \"), wielka litera Ä (kod ósemkowy \304), znak \ (znak specjalny \\), maa litera ä (kod ósemkowy \344), znak backspace (znak specjalny \b, kod dziesitny 8) i znak newline (znak specjalny \n, kod dziesitny 10).
W kodzie programu podstawimy wiersz String str = "#\"\304\\\344\b\n"; i uzyskamy wynik: Znaki: #"Ä\ä Znak
#
"
Ä
\
ä
Kod znaku isDigit() isLetter() isLetterOrDigit() isLowerCase() isSpaceChar() isUpperCase() isWhitespace()
35 false false false false false false false
34 false false false false false false false
196 false true true false false true false
92 false false false false false false false
228 false true true true false false false
8 false false false false false false false
10 false false false false false false true
Rozdzia 5. i Rozwizania zada
129
7. Liczby cakowite typu int i klasa Integer Zadanie 7.1. StaticInteger.java, Z07 1.java Objanienia staych i wybranych metod statycznych klasy Integer opakowujcej typ prosty int zawarto w tekcie programu. public class StaticInteger { public static void main(String args[]) { System.out.println("Wybrane stae i metody statyczne klasy Integer\n"); System.out.println("Warto minimalna typu int: "+ Integer.MIN VALUE); System.out.println("Warto maksymalna typu int: "+ Integer.MAX VALUE); System.out.println("Rozmiar (w bitach) typu int: "+Integer.SIZE); int a = 179; System.out.println("Liczba cakowita a = "+a+ " zapis (cig cyfr):"); System.out.println("w systemie binarnym: "+ Integer.toBinaryString(a)); System.out.println("w systemie ósemkowym: "+ Integer.toOctalString(a)); System.out.println("w systemie szesnastkowym: "+ Integer.toHexString(a)); System.out.println("w systemie dziesitkowym: "+ Integer.toString(a)); System.out.println("w systemie czwórkowym: "+ Integer.toString(a, 4)); int b = Integer.parseInt(" 177"); System.out.println("b = "+b); int c = Integer.parseInt(" 177", 8); System.out.println("c = "+c); System.out.println("Metoda signum():"); System.out.println("Znak liczby a: "+Integer.signum(a)); System.out.println("Znak liczby b: "+Integer.signum(b)); System.out.println("Znak liczby 0: "+Integer.signum(0)); } }
Zwrómy uwag na moliwo parsowania tego samego cigu znaków (np. "-177") w ukadach pozycyjnych o rónej podstawie. Skompilujmy i uruchommy ten program dla rónych wartoci zmiennej a. Porównajmy sposób zapisu liczby dodatniej i ujemnej (np. 179 i –179) w rónych systemach liczbowych.
Zadanie 7.2. ObjectInteger.java, Z07 2.java Objanienia metod zawarto w kodzie lub komentarzach do kodu. public class ObjectInteger { public static void main(String args[]) { System.out.println("Wybrane metody obiektów klasy Integer\n");
130
Programowanie w jzyku Java /* Konstruktor tworzcy nowy obiekt typu Integer reprezentujcy podan liczb, w tym przypadku 1024. */ Integer a = new Integer(1024); /* Konstruktor tworzcy nowy obiekt klasy Integer na podstawie podanego acucha znaków (cigu cyfr). Zero nieznaczce zostanie pominite. */ Integer b = new Integer("02000"); /* Statyczna metoda decode() zwraca obiekt reprezentujcy liczb zakodowan w acuchu znaków - 0 na pocztku oznacza liczb zapisan w systemie ósemkowym. */ Integer c = Integer.decode("02000"); /* Jw. - pocztek cigu w postaci 0x oznacza liczb zakodowan w systemie szesnastkowym. */ Integer d = Integer.decode("0x2000"); System.out.println("a = "+a); System.out.println("b = "+b); System.out.println("c = "+c); System.out.println("d = "+d); /* Metoda equals() sprawdza, czy obiekt wywoujcy t metod jest równy obiektowi podanemu jako parametr. Wynik porównania jest wartoci logiczn (true albo false). */ System.out.println("Czy obiekt a jest równy obiektowi b? "+ a.equals(b)); System.out.println("Czy obiekt a jest równy obiektowi c? "+ a.equals(c)); /* Metoda compareTo() porównuje obiekt wywoujcy t metod z obiektem stanowicym parametr. Wynik jest jedn z liczb: -1, 0 i 1. 0 oznacza równo obiektów, -1 oznacza, e pierwszy obiekt (wywoujcy metod) jest mniejszy od drugiego obiektu (parametru), a 1 oznacza, e pierwszy obiekt jest wikszy od drugiego). */ System.out.println("Porównanie obiektu a z obiektem c? "+ a.compareTo(c)); System.out.println("Porównanie obiektu c z obiektem d? "+ c.compareTo(d)); System.out.println("Porównanie obiektu d z obiektem c? "+ d.compareTo(c)); /* Metoda statyczna valueOf() zwraca obiekt klasy Integer reprezentujcy warto okrelon jako parametr - liczba cakowita lub acuch znaków (cyfr dziesitnych). */ a = Integer.valueOf(1000); b = Integer.valueOf("1000"); /* Drugi parametr metody statycznej valueOf okrela podstaw systemu liczbowego, w którym naley zinterpretowa cig cyfr podany jako pierwszy parametr metody. */ c = Integer.valueOf("1000", 2); // 1000 w ukadzie binarnym d = Integer.valueOf("1000", 16); // 1000 w ukadzie szesnastkowym System.out.println("a = "+a); System.out.println("b = "+b); System.out.println("c = "+c); System.out.println("d = "+d); /* Tu wstaw ponownie kod do porównywania obiektów. */ } }
Rozdzia 5. i Rozwizania zada
131
Metoda obj1.equals(obj2) zwraca warto false, gdy obiekty maj róne wartoci, i true w przypadku równych wartoci wszystkich pól obiektów obj1 i obj2 (o ile w implementacji metody equals() nie zdecydujemy inaczej). Uycie operatora porównania obj1 == obj2 zwróci nam wynik porównania referencji obiektów, a nie ich wartoci. Metoda obj1.compareTo(obj2) zwraca 0, gdy obiekty s równe; –1, gdy warto obj1 jest mniejsza od wartoci obj2, albo 1, gdy warto obj1 jest wiksza od wartoci obj2.
Zadanie 7.3. Dodawanie.java, Z03 3.java Na listingu przedstawiono trzy warianty rozwizania zadania (w jednym pliku), rónice si sposobem obliczenia i wywietlenia wyniku. W pierwszym przypadku najpierw jest wywietlany tekst "a + b = " przy uyciu metody print(), a potem obliczana jest warto wyraenia a+b. Wynik przekazany jest jako parametr wywoania metody println(). W drugim przypadku nastpuje poczenie (dodawanie) tekstu z wynikiem dodawania wartoci zmiennych. Poniewa dziaania dodawania wykonywane s od strony lewej do prawej, to do tekstu dodana jest warto zmiennej a (skonwertowanej na tekst), a nastpnie do wyniku (bdcego acuchem znaków) dodawana jest druga liczba b (zamieniona na tekst). W efekcie zamiast sumy dwóch liczb otrzymujemy sum acuchów cyfr reprezentujcych te liczby. Aby uzyska prawidowy rezultat, naley zmieni kolejno wykonywania dziaa (uy nawiasów). Najpierw bdzie obliczona suma wartoci zmiennych (a+b), a nastpnie wynik zostanie zamieniony na acuch znaków i doczony z prawej strony tekstu "a + b =". W trzecim przypadku uywamy dodatkowej zmiennej c do przechowania sumy a+b. Wywietlenie wyniku nie sprawia nam adnych niespodzianek. public class Dodawanie { public static void main(String args[]) { int a = 2451, b = 375; System.out.println("a = "+a+", b = "+b); /* wariant 1. */ System.out.print("a + b = "); System.out.println(a+b); /* wariant 2. */ System.out.println("a + b = "+a+b); // bd System.out.println("a + b = "+(a+b)); /* wariant 3. */ int c = a+b; System.out.println("a + b = "+c); } }
132
Programowanie w jzyku Java
Zadanie 7.4. Z07 4a.java, Z07 4b.java, Z07 4c.java, Z07 4d.java a) Odejmowanie.java — wzorujc si na rozwizaniu zadania 7.3, zbudujemy
program: public class Odejmowanie { public static void main(String args[]) { int a = 2451, b = 375; System.out.println("a = "+a+", b = "+b); /* Wariant 1. - osobne wywietlanie tekstu i liczby. */ System.out.print("a b = "); System.out.println(a b); /* Wariant 2. - bdny wynik. */ // System.out.println("a b = "+a b); // le System.out.println("a b = "+(a b)); // dobrze /* Wariant 3. - wprowadzamy dodatkow zmienn c. */ int c = a b; System.out.println("a b = "+c); } }
Zauwamy, e w rozwizaniu zadania 7.3 instrukcja System.out.println("a + b = "+a+b); dawaa bdny wynik (w stosunku do treci zadania), natomiast w przypadku odejmowania instrukcja o postaci System.out.println("a — b = "+a–b); si nie skompiluje. Nie ma odejmowania acuchów znaków! Poniewa operatory + i – maj ten sam priorytet, naley uy nawiasów w celu zmiany kolejnoci wykonywania dziaa System.out.println("a — b = "+(a-b));. b) Mnoenie.java — program ten budujemy w podobny sposób jak program
7.3 i 7.4a. public class Mnoenie { public static void main(String args[]) { int a = 2451, b = 375; System.out.println("a = "+a+", b = "+b); System.out.println("a * b = "+a*b); } }
Na powyszym listingu przedstawiono tylko jeden z moliwych wariantów rozwizania zadania (zob. rozwizania zada 7.3 i 7.4a). Uwaga przedstawiona w rozwizaniu zadania 7.4a nie jest ju aktualna — operator mnoenia * ma wyszy priorytet ni operator +, wic uycie nawiasu nie jest konieczne. Kod w tej postaci skompiluje si i obliczenia zostan wykonane poprawnie. c) Dzielenie.java — kod jest zupenie podobny do tego z rozwizania zadania 7.4b (operator * zastpiono operatorem /). public class Dzielenie { public static void main(String args[]) { int a = 2451, b = 375; System.out.println("a = "+a+", b = "+b); System.out.println("a / b = "+a/b); } }
Rozdzia 5. i Rozwizania zada
133
Operator dzielenia ma wyszy priorytet od operatora dodawania, wic uycie nawiasów nie jest konieczne (zob. uwagi do rozwiza zada 7.3, 7.4a i 7.4b). d) Reszta.java — wyraenie a%b oblicza reszt z dzielenia liczby cakowitej a przez liczb cakowit b. Operator % ma wyszy priorytet od operatora (+). public class Reszta { public static void main(String args[]) { int a = 2451, b = 375; System.out.println("a = "+a+", b = "+b); System.out.println("a % b = "+a%b); System.out.println("b % a = "+b%a); } }
Zadanie 7.5. Dzielenie2.java, Z07 5.java Dzielenie z reszt wykonujemy dla wybranej pary liczb. Zmieniamy znaki tych liczb tak, aby uzyska wszystkie moliwe pary znaków dzielnej i dzielnika. public class Dzielenie2 { public static void main(String args[]) { int a = 153, b = 15; System.out.println("a = "+a+", b = "+b); System.out.println("a : b = "+a/b+" r. "+a%b+"\n"); b = 15; System.out.println("a = "+a+", b = "+b); System.out.println("a : b = "+a/b+" r. "+a%b+"\n"); a = 153; System.out.println("a = "+a+", b = "+b); System.out.println("a : b = "+a/b+" r. "+a%b+"\n"); b = 15; System.out.println("a = "+a+", b = "+b); System.out.println("a : b = "+a/b+" r. "+a%b+"\n"); } }
Zauwamy, e reszta z dzielenia przyjmuje znak dzielnej, natomiast znak ilorazu zaley od znaków dzielnej i dzielnika (iloraz jest dodatni, gdy dzielna i dzielnik maj ten sam znak — ujemny, gdy operandy maj róne znaki).
Zadanie 7.6. Suma.java, Z07 6.java Z tablicy argumentów odczytujemy dwa argumenty: args[0] i args[1]. Zamieniamy acuchy znaków na liczby cakowite (stosujemy statyczn metod parseInt z klasy Integer) i obliczamy ich sum. public class Suma { public static void main(String args[]) { int suma = Integer.parseInt(args[0])+Integer.parseInt(args[1]); System.out.println("Suma S = "+suma); } }
134
Programowanie w jzyku Java
Aplikacj uruchamiamy z dwoma parametrami, np. java Suma 231 -347. Jeli podczas uruchomienia nie podamy dwóch argumentów lub argumenty nie bd poprawnie zapisanymi liczbami, to aplikacja przerwie prac i pojawi si odpowiedni komunikat.
Zadanie 7.7. Sumuj.java Aplikacj uruchamiamy z kilkoma parametrami, np. java Sumuj 127 -242 391. Deklarujemy i inicjujemy zmienn cakowit int suma = 0;. Odczytujemy kolejne argumenty z tablicy args w ptli for, zamieniamy je na liczby cakowite i dodajemy do zmiennej suma. public class Sumuj { public static void main(String args[]) { int suma = 0; for(String argument: args) suma += Integer.parseInt(argument); System.out.println("Suma S = "+suma); } }
W obliczeniach moemy równie posuy si metodami z klasy Integer: suma += Integer.valueOf(argument).intValue();
Najpierw tworzymy obiekt Integer.valueOf(argument), a nastpnie przy wykorzystaniu metody intValue() zwracamy warto jedynego pola obiektu (typ int). Taki sam efekt uzyskamy z uyciem metody decode(): suma += Integer.decode(argument).intValue();
W tym przypadku argumenty mona podawa równie w postaci szesnastkowej (np. 0xAF, 0XAF lub #1AF0) albo ósemkowej (0742). Moemy w wyraeniu sumujcym uy polecenia new i konstruktora: suma += new Integer(argument).intValue();
Gdy pominiemy metod intValue() w powyszych wariantach rozwizania, nie spowoduje to bdu (w Javie od wersji 5. wprowadzono autoboxing). Podczas kompilacji wyraenia obiekt klasy Integer jest automatycznie zamieniany na warto typu int. Jeli uruchomimy aplikacj bez argumentów, to otrzymamy sum 0. Jeli natomiast który z parametrów nie bdzie liczb cakowit, to dziaanie programu zostanie przerwane.
Zadanie 7.8. Zamiana.java, Z07 8.java Aplikacj uruchamiamy z dwoma parametrami — pierwszy parametr interpretujemy jako podstaw systemu (int radix = Integer.parseInt(args[0])), a drugi bdzie zamienian liczb (int n = Integer.parseInt(args[1])). Stosujc metod toString z klasy Integer, zamieniamy liczb cakowit n na acuch znaków str reprezentujcy t liczb w systemie pozycyjnym o podstawie radix. Podstawa radix powinna by liczb z zakresu od 2 do 36; wyjcie poza ten zakres nie spowoduje bdów — zostanie przyjta domylna warto podstawy (radix = 10).
Rozdzia 5. i Rozwizania zada
135
public class Zamiana { public static void main(String args[]) { int radix = Integer.parseInt(args[0]); int n = Integer.parseInt(args[1]); String str = Integer.toString(n, radix); System.out.println(args[1]+"[10] = "+str+"["+radix+"]"); } }
Uruchamiajc aplikacj, np. java Zamiana 2 255, otrzymamy wynik 255[10] = 1111 1111[2].
Zadanie 7.9. Zamiana2.java, Z07 9.java Pierwszy parametr interpretujemy jako podstaw systemu (int radix = Integer.parse Int(args[0])), a drugi bdzie cigiem cyfr w systemie pozycyjnym o podstawie radix. Stosujc metod parseInt z klasy Integer, zamieniamy acuch znaków args[1] reprezentujcy liczb w systemie o podstawie radix na liczb w systemie dziesitkowym (int n = Integer.parseInt(args[1], radix)). public class Zamiana2 { public static void main(String args[]) { int radix = Integer.parseInt(args[0]); int n = Integer.parseInt(args[1], radix); System.out.println(args[1]+"["+radix+"] = "+n+"[10]"); } }
Wywoujc aplikacj, np. java Zamiana2 2 11111111, otrzymamy wynik 11111111[2] = 255[10]. Podanie podstawy wykraczajcej poza dopuszczalny zakres lub cigów znaków niebdcych liczbami w wybranym systemie spowoduje przerwanie programu.
8. Inne typy liczb cakowitych w Javie Zadanie 8.1. LongNumber.java, Z08 1.java, Z08 1a.java Po skompilowaniu i uruchomieniu aplikacji (z listingu 8.1) otrzymamy w konsoli taki wynik: n = 9223372036854775807 BIN: 111111111111111111111111111111111111111111111111111111111111111 HEX: 7fffffffffffffff m = 9223372036854775808 BIN: 1000000000000000000000000000000000000000000000000000000000000000 HEX: 8000000000000000 Zamiana na typ int, m = 1 BIN: 11111111111111111111111111111111 HEX: ffffffff Zamiana na typ int, m = 0 BIN: 0 HEX: 0
136
Programowanie w jzyku Java
Przeanalizujmy fragmenty kodu ródowego: long n = Long.MAX VALUE; System.out.println("n = "+n); System.out.println("BIN: "+Long.toBinaryString(n)); System.out.println("HEX: "+Long.toHexString(n));
Najwiksz liczb cakowit dodatni 64-bitow ze znakiem (typu long) jest 263–1 (n = 9223372036854775807). W klasie opakowujcej Long reprezentuje t liczb staa MAX VALUE. Stosujc statyczn metod toBinaryString dla tej liczby, zobaczymy jej posta binarn — cig 63 cyfr 1; szedziesity czwarty (najstarszy) bit ma warto 0 i nie jest wywietlany (pominicie tzw. zer nieznaczcych). W postaci szesnastkowej, uzyskanej metod statyczn toHexString, otrzymujemy szesnacie cyfr — cyfr 7 (binarnie 0111) i pitnacie cyfr f (binarnie 1111, dziesitnie 15). long m = n+1; System.out.println("m = "+m); System.out.println("BIN: "+Long.toBinaryString(m)); System.out.println("HEX: "+Long.toHexString(m));
Po dodaniu liczby 1 otrzymamy (zgodnie z reguami dziaa na liczbach binarnych) cig bitów zoony z jedynki i 63 zer. Odpowiada to liczbie dziesitnej –263 (–9223 372036854775808). Najstarszy bit (1) jest w tym przypadku bitem znaku i oznacza liczb ujemn (w kodzie uzupenie do dwóch). W postaci szesnastkowej mamy cyfr 8 (binarnie 1000) i pitnacie cyfr 0 (binarnie 0000). Long max = new Long(n); System.out.println("Zamiana na typ int, m = "+max.intValue()); System.out.println("BIN: "+Integer.toBinaryString(max.intValue())); System.out.println("HEX: "+Integer.toHexString(max.intValue()));
Tworzymy obiekt max (reprezentujcy liczb n) klasy opakowujcej Long. Stosujc metod intValue, otrzymamy liczb typu int równ –1 (w postaci binarnej 11111111111 111111111111111111111 — 32 bity 1). Z liczby omiobajtowej (long) obcito cztery starsze bajty i zostawiono reszt (cztery modsze bajty) — liczb 32-bitow typu int. Podobny efekt mona uzyska, wykonujc rzutowanie liczby typu long na typ int. System.out.println("Zamiana na typ int, m = "+(int)m); System.out.println("BIN: "+Integer.toBinaryString((int)m)); System.out.println("HEX: "+Integer.toHexString((int)m));
Przy wywietlaniu liczb zostay pominite zera nieznaczce. Zmieniajc warto zmiennej n na minimaln oraz biorc liczb m o jeden mniejsz (Long n = new Long(Long.MIN VALUE); Long),
otrzymamy taki rezultat: n = 9223372036854775808 BIN: 1000000000000000000000000000000000000000000000000000000000000000 HEX: 8000000000000000 m = 9223372036854775807 BIN: 111111111111111111111111111111111111111111111111111111111111111
Rozdzia 5. i Rozwizania zada
137
HEX: 7fffffffffffffff Zamiana na typ int, m = 0 BIN: 0 HEX: 0 Zamiana na typ int, m = 1 BIN: 11111111111111111111111111111111 HEX: ffffffff
Analiz wyniku pozostawiamy Czytelnikowi.
Zadanie 8.2. MinMax.java, Z08 2.java Liczba cakowita n-bitowa ze znakiem ma najmniejsz warto –2n–1 (bit 1 i n–1 bitów 0) i najwiksz warto 2n–1–1 (n bitów 1). W Javie typy proste byte, short, int i long s typami liczb cakowitych ze znakiem, o dugoci (odpowiednio do kolejnoci podanych nazw) 8, 16, 32 i 64 bitów. Nie musimy oblicza wartoci granicznych wedug podanej wyej zasady, gdy klasy opakowujce Byte, Short, Integer i Long zawieraj odpowiednie stae MIN VALUE i MAX VALUE. public class MinMax { public static void main(String args[]) { System.out.println("byte "); System.out.println("short "); System.out.println("int "); System.out.println("long "); } }
Po wykonaniu programu otrzymamy wynik: byte short int long
< < <
32768, 32767> 2147483648, 2147483647> 9223372036854775808, 9223372036854775807>
Zadanie 8.3. MaxPositive.java, Z08 3.java W rozwizaniu zadania wykorzystamy stae z klas opakowujcych proste typy liczbowe: Byte.MAX VALUE, Short.MAX VALUE, Integer.MAX VALUE i Long.MAX VALUE, a take metody toBinaryString i toHexString — z klasy Integer dla typów byte, short i int oraz z klasy Long dla typu long (lub wszystkich wymienionych typów). public class MaxPositive { public static void main(String args[]) { System.out.print("byte "+ Integer.toBinaryString(Byte.MAX VALUE)); System.out.println("\t"+Integer.toHexString(Byte.MAX VALUE)); System.out.print("short "+ Integer.toBinaryString(Short.MAX VALUE)); System.out.println("\t"+Integer.toHexString(Short.MAX VALUE)); System.out.print("int "+ Integer.toBinaryString(Integer.MAX VALUE));
138
Programowanie w jzyku Java System.out.println("\t"+Integer.toHexString(Integer.MAX VALUE)); System.out.print("long "+Long.toBinaryString(Long.MAX VALUE)); System.out.println("\t"+Long.toHexString(Long.MAX VALUE)); } }
Zadanie 8.4. Kodowanie.java, Z08 4.java, Z08 4a.java Po uruchomieniu aplikacji: public class Kodowanie { public static void main(String[] args) { String napis = "kodowanie"; System.out.println("Tekst: "+napis); System.out.print("Cig bajtów:"); byte[] kod = napis.getBytes(); for(byte n : kod) System.out.print(" "+n+","); System.out.println("\b."); } }
uzyskamy nastpujcy wynik: Tekst: kodowanie Cig bajtów: 107, 111, 100, 111, 119, 97, 110, 105, 101.
Zwrómy uwag na sposób wywietlania poszczególnych elementów tablicy (w ptli): odstp, liczba i przecinek. Przecinek po ostatniej liczbie kasujemy, wpisujc znak \b (ang. backspace), a nastpnie stawiamy kropk. Jeli skorzystamy z klasy Arrays (potrzebny bdzie import klasy java.util.Arrays) opakowujcej typy tablicowe, to moemy tablic bajtów kod zamieni na acuch znaków w postaci [107, 111, 100, 111, 119, 97, 110, 105, 101] i wywietli go w konsoli. Uyjemy do tego celu statycznej metody Arrays.toString(), np.: System.out.print("Cig bajtów: "); System.out.println(Arrays.toString(napis.getBytes()));
Zadanie 8.5. Dekodowanie.java, Z08 5.java Na podstawie cigu bajtów tworzymy tablic bajtów byte[] kod = {115, 122, 121, 102, 114}, wywietlamy zawarto tablicy w konsoli (zob. drugi wariant rozwizania zadania 8.4). Na podstawie tablicy bajtów (kod) tworzymy acuch znaków — klasa String posiada odpowiedni konstruktor (String wynik = new String(kod)). import java.util.Arrays; public class Dekodowanie { public static void main(String[] args) { byte[] kod = {115, 122, 121, 102, 114}; System.out.println("Cig bajtów: "+Arrays.toString(kod)); String wynik = new String(kod); System.out.println("Tekst: "+wynik); } }
Rozdzia 5. i Rozwizania zada
139
Zadanie 8.6. DodajCyfry.java, Z08 6a.java, Z08 6b.java a) Liczba podana w postaci acucha znaków (cyfr) nie ma waciwie
ograniczenia liczby cyfr powodowanego zakresem cakowitych typów liczbowych w Javie. Cig cyfr zamieniamy na cig (tablic) odpowiadajcych im bajtów. Podczas sumowania od kolejnych bajtów odejmujemy 48 (kod 0) i uzyskujemy warto liczbow odpowiedniej cyfry. public class DodajCyfry { public static void main(String[] args) { String liczba = "3784596320"; byte[] kod = liczba.getBytes(); int suma = 0; for(byte c: kod) suma += c 48; System.out.println("Liczba naturalna: "+liczba); System.out.println("Suma cyfr: "+suma); } }
b) Jeli liczba zapisana jest w pamici w postaci numerycznej (proponujemy uy typu o najwikszym zakresie, czyli long), to zamieniamy j na acuch
znaków: long n = 3784596320L; String liczba = Long.toString(n);
i kontynuujemy obliczenia wedug podpunktu a). Naley zwróci uwag na sposób zainicjowania zmiennej n — liczby cakowite wiksze od Integer. MAX VALUE (2147483647) s liczbami typu long i reprezentujce je literay musz by zakoczone liter L (mona równie uy maej litery l, ale ten znak moemy pomyli z cyfr 1). Najwiksz liczb, dla której moemy to zadanie wykona, jest Long.MAX VALUE, czyli 9223372036854775807.
Zadanie 8.7. Txt2Hex.java, Z08 7.java Podobnie jak w rozwizaniu zadania 8.4, zamienimy acuch znaków (String napis = "szyfr") na cig bajtów zapisany w tablicy kod (byte[] kod = napis.getBytes()). Wywietlajc zawarto tablicy, zamienimy liczby (n typu byte) na ich reprezentacj szesnastkow (Integer.toHexString(n).toUpperCase()). public class Txt2Hex { public static void main(String[] args) { String napis = "szyfr"; System.out.print(napis+" > "); byte[] kod = napis.getBytes(); for(byte n : kod) System.out.print(Integer.toHexString(n).toUpperCase()); } }
Zadanie 8.8. Hex2Txt.java, Z08 8.java
acuch hex zawiera zakodowany cig znaków (String hex = "737A796672"). Kade dwie cyfry szesnastkowe (bajt) odpowiadaj jednemu znakowi. Tworzymy tablic
140
Programowanie w jzyku Java
bajtów o rozmiarze dwa razy mniejszym od rozmiaru acucha hex (byte[] tmp = new byte[hex.length()/2]). W ptli for z acucha hex pobieramy po dwie cyfry szesnastkowe (hex.substring(2*i,2*i+2)), zamieniamy je na liczby i przechowujemy w tablicy tmp. Na koniec zamieniamy tablic bajtów na acuch znaków (new String(tmp)). public class Hex2Txt { public static void main(String[] args) { String hex = "737A796672"; System.out.print(hex+" > "); byte[] tmp = new byte[hex.length()/2]; for(int i = 0; i < tmp.length; ++i) tmp[i] = Byte.parseByte(hex.substring(2*i,2*i+2), 16); System.out.println(new String(tmp)); } }
9. Typy liczb zmiennoprzecinkowych Zadanie 9.1. DemoDouble.java, Z09 1.java Zobaczmy wyniki pracy programu: Minimalna warto dodatnia: 4.9E 324 BIN: 1 HEX: 0x0.0000000000001p 1022 Liczba przeciwna: 4.9E 324 BIN: 1000000000000000000000000000000000000000000000000000000000000001 HEX: 0x0.0000000000001p 1022
Staa Double.MIN VALUE ma warto najmniejszej liczby dodatniej moliwej do przedstawienia w postaci liczby zmiennoprzecinkowej podwójnej precyzji (typu double), czyli warto 4.9E-324 (4,9·10–324). Jej reprezentacja binarna ma posta (64 bity, w konsoli zera nieznaczce zostay pominite): 0000000000000000000000000000000000000000000000000000000000000001
W skad tej reprezentacji wchodz: 0 (0 oznacza liczb dodatni), 11 bitów cechy 000 00000000 i 52 bity mantysy 0000000000000000000000000000000000000000000000000001. Poniewa wszystkie bity cechy s zerami, wic mantysa jest zdenormalizowana (bez bitu cakowitego 1) i ma posta binarn 0,00000000000000000000000000000000000000 00000000000001 (cyfra 1 na pidziesitej drugiej pozycji po przecinku), a to odpowiada liczbie dziesitnej 2–52. Mnoc mantys przez liczb 21–1023, uzyskamy warto 2-52·21–1023 = 2–1074 = 4,9·10–324. Zapis binarny liczby przeciwnej róni si jedynie bitem znaku: 1 oznacza liczb ujemn. W programie zastosowano nastpujce elementy statyczne z klas Double i Long: Double.MIN VALUE — staa o wartoci najmniejszej liczby dodatniej typu double,
Rozdzia 5. i Rozwizania zada
141
long Double.doubleToLongBits(double) — metoda zamieniajca liczb zmiennoprzecinkow typu double na liczb cakowit typu long o identycznej
reprezentacji binarnej, String Long.toBinaryString(long) — metoda zamieniajca liczb cakowit typu long na acuch zawierajcy reprezentacj binarn tej liczby
(z pominiciem zer nieznaczcych), String Double.toHexString(double) — metoda zamieniajca liczb zmiennoprzecinkow typu double na acuch znaków heksadecymalnych reprezentujcych t liczb; np. w cigu znaków 0x0.0000000000001p-1022
kolejne elementy oznaczaj: 0x — liczba jest zapisana w kodzie szesnastkowym; 0.0000000000001 — zdenormalizowana mantysa — cyfra jednoci 0, 13 cyfr szesnastkowych po przecinku (13·4 = 52 bity mantysy); p–1022 — wykadnik (–1022) zapisany w kodzie dziesitkowym (podstaw potgi jest 2).
Zapis ten reprezentuje liczb zmiennoprzecinkow o wartoci mantysa·21022.
Zadanie 9.2. DoubleBin.java, Z09 2.java
acuch zero zawierajcy 63 znaki 0 przyda si do uzupeniania zer nieznaczcych do 64 bitów w liczbach dodatnich, dla których metoda toBinaryString zera nieznaczce pomija. Liczby lub symbole, których posta binarn chcemy pozna, umieszczamy w tablicy double[] a = {...}. W ptli pobieramy elementy (for(double x : a)...) tej tablicy, wywietlamy ich posta zmiennoprzecinkow w konsoli (System.out.println ("x = "+x)), zamieniamy liczb x typu double na liczb typu long, majc identyczn reprezentacj binarn (Double.doubleToLongBits(x)), a t liczb typu long przedstawiamy w postaci binarnej (String tmp = Long.toBinaryString(...)) — acuch tmp. Z acucha tmp tworzymy acuch bin o dugoci 64 znaków (sowo 64-bitowe), dodajc zera (nieznaczce) na pocztku acucha. Z acucha bin wybieramy bit znaku (bin.charAt(0)), cech (bin.substring(1, 12)) i mantys (bin.substring(12)), przedstawiajc w ten sposób binarn posta liczby lub symbolu zmiennoprzecinkowego. public class DoubleBin { static String zero = "0000000000000000000000000000000000000000000000000000000000000000"; public static void main(String[] args) { double[] a = {0.25, 0.5, 1.0, 2.0, 512.0}; /* podpunkt a) */ for(double x : a) { System.out.println("x = "+x); String tmp = Long.toBinaryString(Double.doubleToLongBits(x)); String bin = zero.substring(0, 64 tmp.length())+tmp; System.out.println("BIN: "+bin); System.out.println("Bit znaku: "+bin.charAt(0)); System.out.println("Cecha: "+bin.substring(1, 12)); System.out.println("Mantysa: "+bin.substring(12));
142
Programowanie w jzyku Java System.out.println(); } } }
a) Wybrane potgi liczby: 0,25; 0,5; 1,0; 2,0; 512,0. x = 0.25 BIN: 0011111111010000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 01111111101 Mantysa: 0000000000000000000000000000000000000000000000000000 x = 0.5 BIN: 0011111111100000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 01111111110 Mantysa: 0000000000000000000000000000000000000000000000000000 x = 1.0 BIN: 0011111111110000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 01111111111 Mantysa: 0000000000000000000000000000000000000000000000000000 x = 2.0 BIN: 0100000000000000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 10000000000 Mantysa: 0000000000000000000000000000000000000000000000000000 x = 512.0 BIN: 0100000010000000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 10000001000 Mantysa: 0000000000000000000000000000000000000000000000000000
Wszystkie liczby s dodatnie (bit znaku 0). Ich cechy s róne od zera, wic mantysy s znormalizowane i równe (binarnie 1,0000…) 1. Cechy kolejnych liczb s równe binarnie 01111111101, 01111111110, 01111111111, 10000000000 i 10000001000, co odpowiada liczbom dziesitnym 1021, 1022, 1023, 1024 i 1032. Po uwzgldnieniu przesunicia –1023 otrzymamy wykadniki –2, –1, 0, 1 i 9. Poniewa mantysa jest równa 1 dla wszystkich liczb z podanego zestawu, to wartoci tych liczb s równe 2–2 = 0,25; 2–1 = 0,5; 20 = 1; 21 = 2 i 29 = 512. b) Podane liczby s potgami liczby 10. double[] a = {0.01, 0.1, 1.0, 10.0, 100.0};
W postaci binarnej nie dostrzeemy adnego zwizku pomidzy tymi liczbami. c) Podane liczby s liczbami dziesitnymi zapisanymi przy uyciu tych
samych cyfr i róni si pooeniem przecinka dziesitnego. double[] a = {1.367, 1367, 1.367e 12, 1.367e12, 13.67,
13.67};
Rozdzia 5. i Rozwizania zada
143
W postaci binarnej nie dostrzeemy adnych podobiestw, z wyjtkiem ostatnich dwu liczb, które s liczbami przeciwnymi (róni si bitem znaku). d) Symbole specjalne (NaN i rf ). double[] a = {Double.NaN, Double.NEGATIVE INFINITY, Double.POSITIVE INFINITY};
Wszystkie symbole specjalne maj cech zoon z samych bitów 1. Mantysa znaku NaN (ang. Not a Number) skada si z bitu 1 i 51 bitów 0. x = NaN BIN: 0111111111111000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 11111111111 Mantysa: 1000000000000000000000000000000000000000000000000000
Symbole nieskoczonoci maj mantysy zoone z bitów 0, a bit znaku decyduje o znaku wartoci. x = Infinity BIN: 1111111111110000000000000000000000000000000000000000000000000000 Bit znaku: 1 Cecha: 11111111111 Mantysa: 0000000000000000000000000000000000000000000000000000 x = Infinity BIN: 0111111111110000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 11111111111 Mantysa: 0000000000000000000000000000000000000000000000000000
e) Dwie reprezentacje zera (dodatnia i ujemna) oraz dodatnie wartoci
ekstremalne. double[] a = {0.0, 0.0, Double.MIN VALUE, Double.MAX VALUE, 2.2250738585072014e 308};
Cecha i mantysa skadaj si z samych bitów 0. To reprezentacja liczby 0.0. Jedynie bit znaku moe przyjmowa warto 0 lub 1. Mamy zatem dwie reprezentacje binarne zera w liczbach zmiennoprzecinkowych — w informatyce uywamy czasem wyrae „zero dodatnie” i „zero ujemne”. x = 0.0 BIN: 0000000000000000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 00000000000 Mantysa: 0000000000000000000000000000000000000000000000000000 x = 0.0 BIN: 1000000000000000000000000000000000000000000000000000000000000000 Bit znaku: 1 Cecha: 00000000000 Mantysa: 0000000000000000000000000000000000000000000000000000
T warto (najmniejsz moliw do zapisania liczb dodatni — sta Double.MIN VALUE) omówiono dokadnie w rozwizaniu zadania 9.1 (mantysa tej liczby nie jest znormalizowana).
144
Programowanie w jzyku Java x = 4.9E 324 BIN: 0000000000000000000000000000000000000000000000000000000000000001 Bit znaku: 0 Cecha: 00000000000 Mantysa: 0000000000000000000000000000000000000000000000000001
Najwiksza moliwa do zapisania liczba zmiennoprzecinkowa (staa Double. MAX VALUE) ma cech 11111111110 (najwiksz, jak mona zapisa na 11 bitach, bo cecha 11111111111 jest zarezerwowana dla symboli specjalnych) i mantys (znormalizowan) zoon z samych bitów 1. x = 1.7976931348623157E308 BIN: 0111111111101111111111111111111111111111111111111111111111111111 Bit znaku: 0 Cecha: 11111111110 Mantysa: 1111111111111111111111111111111111111111111111111111
Binarna mantysa 1,1111111111111111111111111111111111111111111111111111 po przeliczeniu na ukad dziesitkowy ma warto 2–2–52, cecha 11111111110 ma warto 2046, wic warto dziesitna tej liczby wynosi (2–2–52)·22046–1023 = (2–2–52)·21023 = 1,7976931348623157·10308. Kolejna liczba jest najmniejsz liczb dodatni o znormalizowanej mantysie 1,0·21–1023 = 2–1022 = 2,2250738585072014·10-308. x = 2.2250738585072014E 308 BIN: 0000000000010000000000000000000000000000000000000000000000000000 Bit znaku: 0 Cecha: 00000000001 Mantysa: 0000000000000000000000000000000000000000000000000000
Zadanie 9.3. Bin2Float.java, Z09 3.java Cig bitów o dugoci nieprzekraczajcej 32 znaków zapisujemy w acuchu bin. Obliczmy warto cakowit n odpowiadajc podanemu acuchowi cyfr binarnych (int n = Integer.parseInt(bin, 2)). Liczb cakowit typu int zamieniamy na liczb zmiennoprzecinkow typu float o identycznej reprezentacji binarnej (float x = Float.intBitsToFloat(n)). public class Bin2Float { public static void main(String[] args) { String bin ="111110000011110000111000110010"; int n = Integer.parseInt(bin, 2); float x = Float.intBitsToFloat(n); System.out.println("bin: "+bin); System.out.println("int: "+n); System.out.println("float: "+x); } }
Cig bitów 111110000011110000111000110010 reprezentuje liczb zmiennoprzecinkow (float) 0,13970259.
Rozdzia 5. i Rozwizania zada
145
Zadanie 9.4. Bin2Double.java, Z09 4.java Cig bitów o dugoci nieprzekraczajcej 64 znaków zapisujemy w acuchu bin. Obliczmy warto cakowit n (64-bitow, typu long) odpowiadajc podanemu acuchowi cyfr binarnych (long n = Integer.parseLong(bin, 2)). Liczb cakowit typu long zamieniamy na liczb zmiennoprzecinkow typu double o identycznej reprezentacji binarnej (double x = Double.longBitsToDouble(n)). public class Bin2Double { public static void main(String[] args) { String bin ="111110000011110000111000110010"; long n = Long.parseLong(bin, 2); double x = Double.longBitsToDouble(n); System.out.println("bin: "+bin); System.out.println("long: "+n); System.out.println("double: "+x); } }
Cig bitów 111110000011110000111000110010 reprezentuje liczb zmiennoprzecinkow (double) 5,144083374E-315 (porównaj ten wynik z wynikiem uzyskanym w zadaniu 9.3).
Zadanie 9.5. Bin2Double.java, Z09 5.java W symbolach specjalnych cecha ma wszystkie bity równe 1 (w cigach bitów symbole te zostay wyrónione przez pogrubienie). Oto reprezentacje binarne trzech symboli specjalnych): nieskoczono ujemna ( f ) 11111111100000000000000000000000, nieskoczono dodatnia ( f ) 01111111100000000000000000000000, nie liczba (NaN) 01111111111111111111111111111111 (co najmniej najstarszy bit mantysy musi by równy 1). public class TestBinFloat { public static void main(String[] args) { float x = Float.intBitsToFloat(Integer.parseInt(args[0], 2)); System.out.println(args[0]+" > "+x); } }
Kod wyglda na poprawny, ale niestety kopoty sprawia metoda Integer.parseInt (String, int), która nie akceptuje (zgodnie z dokumentacj) cigów cyfr binarnych 32-bitowych, majcych najstarszy bit 1 (liczby cakowite ujemne w kodzie uzupenie do 2), natomiast dopuszcza zastosowanie znaku – (minus) przed cigiem cyfr binarnych, nie duszym ni 31 bitów. Aby wyznaczy liczb typu float majc reprezentacj binarn 111111111000000000 00000000000000, powinnimy zanegowa w tym cigu wszystkie bity 0000000001111 1111111111111111111, a nastpnie doda 1 (dodawanie zgodnie z reguami dodawania liczb w systemie binarnym). Otrzymamy w ten sposób cig cyfr 000000001000000000 00000000000000, przed którym stawiamy znak minus (–00000000100000000000000000
146
Programowanie w jzyku Java 000000). Zera nieznaczce mona pomin — ich obecno jednak nie wpywa na wynik (w tym przypadku –Infinity, czyli nieskoczono ujemna).
Rozwaana sytuacja nie obejmuje najmniejszej liczby typu int (binarnie 1000000000 0000000000000000000000), której w typie float odpowiada warto –0.0 (zero ujemne!). Moemy o tym si przekona, wykorzystujc nastpujcy wiersz kodu: System.out.println(Float.intBitsToFloat(Integer.MIN VALUE));
Rozdzia 6.
Rozwizania zada 10. Wywietlanie sformatowanych wyników w konsoli. Stae i metody z klasy Math Zadanie 10.1. Z10 1.java Najprostszym rozwizaniem jest uycie metody printf() wprowadzonej w J2SE ver. 5.0 (1.5). Umieszczony w acuchu formatujcym "4/7 = %.5f\n" cig znaków %.5f jest specyfikatorem okrelajcym, e parametr x podstawiony w miejsce specyfikatora ma by zinterpretowany jako liczba zmiennoprzecinkowa (f) i wywietlona z precyzj 5 miejsc po przecinku (.5). Symbol % sygnalizuje, e wystpujce po nim znaki tworz specyfikator. public class Z10 1 { public static void main(String[] args) { double x = (double)4/7; System.out.printf("4/7 = %.5f\n", x); } }
Poznane wczeniej metody print() i println() równie pozwalaj wywietli liczby z okrelon precyzj, pod warunkiem e odpowiednio zaokrglimy wynik. Pomnómy warto zmiennej x przez 100000 (przesunicie przecinka o 5 miejsc w prawo), dodajmy 0.5 i obetnijmy cz uamkow liczby (konwersja liczby zmiennoprzecinkowej na liczb cakowit przez rzutowanie), a nastpnie podzielmy wynik przez 100000.0 (dzielimy liczb cakowit przez liczb zmiennoprzecinkow, aby uzyska wynik zmiennoprzecinkowy). Otrzymany rezultat jest poprawnym zaokrgleniem wartoci x do 5 miejsc po przecinku. double y = (int)(100000*x+0.5)/100000.0; System.out.println("4/7 = "+y);
148
Programowanie w jzyku Java
Moemy zastosowa zaokrglenie przy uyciu metody round(). y = Math.round(100000*x+0.5)/100000.0;
Podobne obliczenia moemy zrealizowa z zastosowaniem obiektu klasy Double. y = new Double(100000*x+0.5).intValue()/100000.0;
Inn moliwo stwarza metoda format() klasy String: System.out.println(String.format("4/7 = %.5f", x));
Zauwamy podobiestwo pomidzy pierwszym i ostatnim przypadkiem (sposób tworzenia acucha znaków). Uzyskany wynik jest zgodny z ustawieniami lokalnymi komputera: 0,57143 (przecinek dziesitny). W pozostaych przypadkach metoda println() wywietla liczby dziesitne z kropk.
Zadanie 10.2. Z10 2.java W pakiecie java.lang zdefiniowano klas Math zawierajc wartoci przyblione staych e i S oraz róne funkcje matematyczne. Dostp do staych lub funkcji otrzymujemy, podajc nazw klasy, kropk i nazw staej lub funkcji, np. Math.E, Math.PI (nazwy staych piszemy zwyczajowo wielkimi literami1) lub Math.sqrt(x) — x jest argumentem funkcji sqrt (ang. square root — pierwiastek kwadratowy). public class Z10 2 { public static void main(String[] System.out.printf("Liczba e System.out.printf("Liczba pi System.out.printf("Liczba fi } }
args) { = %15.10f\n", Math.E); = %15.10f\n", Math.PI); = %15.10f\n", (1+Math.sqrt(5))/2);
Moemy statycznie importowa klas Math i w zapisie wzorów pomin nazw klasy. import static java.lang.Math.*; public class Z10 2a { public static void main(String[] System.out.printf("Liczba e System.out.printf("Liczba pi System.out.printf("Liczba fi } }
args) { = %15.10f\n", E); = %15.10f\n", PI); = %15.10f\n", (1+sqrt(5))/2);
Zadanie 10.3. Z10 3.java W klasie Math oprócz funkcji sqrt() obliczajcej pierwiastek kwadratowy zdefiniowano funkcj cbrt() obliczajc pierwiastek trzeciego stopnia (ang. cube root — pierwiastek szecienny). W ptli typu for each zmienna n przyjmuje kolejno wartoci zapisane w tablicy dane. Dla kadej wartoci zmiennej n metoda printf() wywietla w konsoli zgodnie z acuchem formatujcym: 1
Standard kodowania zaleca pisanie nazw staych wielkimi literami; ostateczna decyzja w tej sprawie naley do programujcego.
Rozdzia 6. i Rozwizania zada
149
%3d — na polu o szerokoci 3 znaków liczb cakowit n; %15.8f — na polu o szerokoci 15 znaków liczb zmiennoprzecinkow (warto wyraenia sqrt(n)) z dokadnoci do 8 miejsc po przecinku; %15.8f — na polu o szerokoci 15 znaków liczb zmiennoprzecinkow (warto wyraenia cbrt(n)) z dokadnoci do 8 miejsc po przecinku; \n — znak koca linii; kursor przechodzi na pocztek nowego wiersza. import static java.lang.Math.*; public class Z10 3 { public static void main(String[] args) { int[] dane = {2, 3, 5, 7, 9, 11, 13, 17}; for(int n : dane) System.out.printf("%3d%15.8f%15.8f\n", n, sqrt(n), cbrt(n)); } }
Zadanie 10.4. Z10 4.java Funkcja pow (ang. power — potga) z klasy Math posiada dwa parametry. Pierwszy jest 1
podstaw, a drugi wykadnikiem obliczanej potgi. Wzór x sa w postaci x = Math.pow(5, 1.0/n).
n
5
5 n moemy zapi-
public class Z10 4 { public static void main(String[] args) { int[] dane = {2, 3, 4, 5, 6, 7, 8, 9, 10}; for(int n : dane) { double x = Math.pow(5, 1.0/n); System.out.printf("Pierwiastek %2d stopnia z 5: %f\n", n, x); } } }
Precyzja 6 miejsc po przecinku jest domylnie ustawiana dla metody printf(), wic w tym zadaniu uyto specyfikatora %f zamiast %.6f. Zwrómy równie uwag na sposób obliczania wykadnika — wyraenie 1.0/n daje nam zmiennoprzecinkow warto uamka (1/n — dzielenie cakowite daoby wykadnik równy 0).
Zadanie 10.5. Z10 5.java Najpierw wywietlamy wiersz nagówka, rezerwujc na pierwsz kolumn 4 znaki (rozmiar sowa Znak) i na pozostae po 10 znaków (specyfikator %10s — pole o szerokoci 10 znaków dla acucha znaków, s — string).
acuch znaków "ABCDEFGHIJKLMNOPQRSTUVWXYZ" zamieniamy, stosujc metod toChar Array(), na tablic znaków znaki. W ptli for each przegldamy zawarto tablicy znaków i wywietlamy w konsoli znak z oraz kod tego znaku (int)z (rzutowanie wartoci typu char na typ int). W specyfikatorach wystpuj symbole %1$ i %2$. W miejsce %1$ wstawiana jest warto pierwszego parametru (znak z), a w miejsce %2$ — warto drugiego parametru (kod znaku (int)z).
150
Programowanie w jzyku Java public class Z10 5 { public static void main(String[] args) { System.out.printf("Znak%10s%10s%10s\n", "OCT", "DEC", "HEX"); char[] znaki = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); for(char z : znaki) { System.out.printf("%1$3c %2$10o%2$10d%2$10X\n", z, (int)z); } } }
Przeanalizujmy specyfikatory w acuchu formatujcym: %1$3c — zmienna typu char (pierwszy parametr) jest wywietlana na polu
szerokoci 3 znaków; %2$10o — liczba cakowita (drugi parametr) wywietlana jest w systemie
ósemkowym (oktalnym) na polu o szerokoci 10 znaków; %2$10d — liczba cakowita (drugi parametr) wywietlana jest w systemie
dziesitnym (decymalnym) na polu o szerokoci 10 znaków; %2$10X — liczba cakowita (drugi parametr) wywietlana jest w systemie
szesnastkowym (heksadecymalnym) na polu o szerokoci 10 znaków. Cyfry szesnastkowe (ABCDEF) wywietlane s wielkimi literami.
Zadanie 10.6. Z10 6.java Metoda (funkcja) toDegrees() z klasy Math zamienia miar kta podan w radianach na miar wyraon w stopniach. Symbol stopnia w tekcie uzyskujemy, wpisujc znak '\u00B0'. public class Z10 6 { public static void main(String[] args) { double alfa = Math.toDegrees(1); // 1 radian w stopniach System.out.println("1 rad = "+alfa+"\u00B0"); int st, min, sek; st = (int)alfa; min = (int)((alfa st)*60+0.5); System.out.printf("1 rad = %d\u00B0%02d\'\n", st, min); min = (int)((alfa st)*60); sek = (int)((alfa st min/60.0)*3600+0.5); System.out.printf("1 rad = %d\u00B0%02d\'%02d\"\n", st, min, sek); } }
Aby zrozumie algorytm zamiany miary stopniowej kta wyraonej uamkiem dziesitnym na stopnie (wyraone liczb cakowit), minuty i sekundy ktowe, przeled my rachunek dla kta o mierze 1 radiana: 1 rad = 57.29577951308232° — wynik dziaania metody Math.toDegrees(1);. 1 rad = 57°18' — liczba stopni jest czci cakowit liczby 57.29577951308232 (st = (int)alfa;), a liczba minut jest czci cakowit
iloczynu 0,29577951308232·60 = 17,7467707849392, po zaokrgleniu (min = (int)((alfa-st)*60+0.5);).
Rozdzia 6. i Rozwizania zada
151
1 rad = 57°17'45" — tym razem nie zaokrglamy liczby minut, ale bierzemy tylko cz cakowit (min = (int)((alfa-st)*60);). Liczba sekund jest
równa iloczynowi 0,7467707849392·60 = 44,806247096352 zaokrglonemu do czci cakowitej (sek = (int)((alfa-st-min/60.0)*3600+0.5);).
Zadanie 10.7. Z10 7.java Metoda (funkcja) toRadians() z klasy Math zamienia miar kta podan w stopniach 1 1 na miar w radianach. Obliczenia wykonamy dla liczb 1 (1°), (1') i (1"). 60 3600 public class Z10 7 { public static void main(String[] args) { double rad = Math.toRadians(1.0); System.out.printf("1\u00B0 = %.15f rad\n", rad); rad = Math.toRadians(1.0/60); System.out.printf("1\' = %.15f rad\n", rad); rad = Math.toRadians(1.0/3600); System.out.printf("1\" = %.15f rad\n", rad); } }
Zadanie 10.8. Z10 8.java a 3 jest jednoczenie sic 5 nusem jednego kta ostrego i cosinusem drugiego kta. Stosujc funkcje odwrotne (dostpne w klasie Math), moemy wyznaczy miary któw ostrych wyraone w radianach: alfa = Math.asin(a/c) i beta = Math.acos(a/c). Wedug algorytmu opisanego w rozwizaniu zadania 10.7 moemy zamieni miary w radianach na miar w stopniach, stopniach i minutach oraz stopniach, minutach i sekundach i sformuowa odpowiedzi.
W trójkcie egipskim o bokach a = 3, b = 4 i c = 5 iloraz
public class Z10 8 { public static void main(String[] args) { double a = 3.0, b = 4.0, c = 5.0; double alfa, beta; int st, min; // do podpunktu c) i d) int sek; // do podpunktu c) alfa = Math.asin(a/c); beta = Math.acos(a/c); /* odpowied a) */ System.out.printf("alfa = %.4f rad\nbeta = %.4f rad", alfa, beta); /* odpowied b) */ System.out.println(); alfa = Math.toDegrees(alfa); beta = Math.toDegrees(beta); System.out.printf("alfa = %.1f\u00B0\nbeta = %.1f\u00B0", alfa, beta); /* odpowied c) */ System.out.println(); st = (int)alfa; min = (int)((alfa st)*60+0.5); System.out.printf("alfa = %d\u00B0%02d\'\n", st, min);
152
Programowanie w jzyku Java st = (int)beta; min = (int)((beta st)*60+0.5); System.out.printf("beta = %d\u00B0%02d\'\n", st, min); /* odpowied d) */ System.out.println(); st = (int)alfa; min = (int)((alfa st)*60); sek = (int)((alfa st min/60.0)*3600+0.5); System.out.printf("alfa = %d\u00B0%02d\'%02d\"\n", st, min, sek); st = (int)beta; min = (int)((beta st)*60); sek = (int)((beta st min/60.0)*3600+0.5); System.out.printf("beta = %d\u00B0%02d\'%02d\"\n", st, min, sek); } }
11. Wczytywanie danych — klasa Scanner Zadanie 11.1. Z11 1.java Zaczynamy od utworzenia obiektu input klasy Scanner odczytujcego dane ze standardowego wejcia System.in. Zgodnie z treci zadania dane wejciowe mog by uamkami dziesitnymi, wic uyjemy zmiennej typu float (liczby zmiennoprzecinkowej pojedynczej precyzji) lub double (liczby zmiennoprzecinkowej podwójnej precyzji). Dla kadego typu danych mamy odrbn metod wczytujc dane ze strumienia: float t = input.nextFloat();
lub: double t = input.nextDouble();
Dane wprowadzamy w postaci liczby cakowitej lub uamka dziesitnego (z przecinkiem). Dopuszczalny jest równie format naukowy, np. 2,35e2 (2,35·102). import java.util.Scanner; public class Z11 1 { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Podaj temperatur w \u00B0C, t = "); double t = input.nextDouble(); System.out.printf("%.1f\u00B0C = %.1f\u00B0F\n", t, t*1.8+32); input.close(); } }
Dane wejciowe i wynik s wywietlane z dokadnoci do jednego miejsca po przecinku (specyfikator w acuchu formatujcym %.1f). Symbol ° (stopnia) wprowadzany jest jako znak \u00B0 (Unicode). Na koniec nie zapomnijmy o zamkniciu skanera input.close().
Rozdzia 6. i Rozwizania zada
153
Ze strumienia danych moemy pobra kolejny token (acuch znaków do najbliszego znaku biaego — odstpu, tabulatora lub koca wiersza): String s = input.next();
i zamieni go na liczb zmiennoprzecinkow, stosujc odpowiedni metod statyczn klasy Float lub Double: float t = Float.parseFloat(s);
lub: float t = Float.valueOf(s);
lub: double t = Double.parseDouble(s);
lub: double t = Double.valueOf(s);
Nie jest to rozwizanie korzystne — dane liczbowe bdziemy musieli wprowadza z kropk dziesitn (konwencja angielska), a wyniki bd wywietlane z przecinkiem. Lepiej uywa zlokalizowanych metod nextFloat() lub nextDouble().
Nie jest konieczne tworzenie obiektu s klasy String, moemy po prostu zapisa w jednym wierszu float t = Float.parseFloat(input.next()).
Zadanie 11.2. Z11 2.java Wzór °F = °C·1,8+32 przeksztacamy na posta °C = (°F-32)/1,8. Temperatura wejciowa wyraona jest liczb cakowit (zgodnie z treci zadania), wic warto pobieramy ze strumienia, stosujc metod input.nextInt(). import java.util.Scanner; public class Z11 2 { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Podaj temperatur w \u00B0F, t = "); int t = input.nextInt(); System.out.printf("%d\u00B0F = %.1f\u00B0C\n", t, (t 32)/1.8); input.close(); } }
Ze strumienia danych moemy pobra kolejny token: String s = input.next();
i zamieni go na liczb cakowit, stosujc wybran metod statyczn klasy Integer: int t = Integer.parseInt(s);
lub: int t = Integer.decode(s);
154
Programowanie w jzyku Java
lub: int t = Integer.valueOf(s);
Moemy ten zapis skróci, eliminujc obiekt s, np.: int t = Integer.valueOf(input.next());
Zadanie 11.3a. Z11 3a.java Dugo przeciwprostoktnej w trójkcie prostoktnym obliczymy ze wzoru c a 2 b2 wynikajcego z twierdzenia Pitagorasa. Do dyspozycji w klasie Math mamy metod sqrt() (pierwiastek kwadratowy) i metod pow() (potgowanie): double c = Math.sqrt(Math.pow(a, 2)+Math.pow(b, 2));
Dwukrotne wywoanie metody pow() w tej sytuacji jest nieekonomiczne. Obliczanie kwadratu liczby wykonamy szybciej, stosujc mnoenie: double c = Math.sqrt(a*a+b*b);
Wprowadzanie danych z klawiatury i wywietlanie wyniku nie sprawi problemu — naley jednak zauway, e program nie kontroluje poprawnoci danych. import java.util.Scanner; public class Z11 3a { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Podaj dugo przyprostoktnej, a = "); double a = input.nextDouble(); System.out.print("Podaj dugo przyprostoktnej, b = "); double b = input.nextDouble(); double c = Math.sqrt(a*a+b*b); System.out.printf("Dugo przeciwprostoktnej c = %.3f\n", c); input.close(); } }
Zadanie 11.3b. Z11 3b.java Zadanie to jest typowym przykadem zastosowania funkcji trygonometrycznych (kta ostrego) do obliczania elementów trójkta prostoktnego (tzw. rozwizywania trójktów). a a . , c sin D a, c c sin D Naley pamita, e funkcje trygonometryczne dostpne w klasie Math (sin, cos i tan
Przyjmujc standardowe oznaczenia, obliczymy: sin D
— tangens) wymagaj podania argumentu (miary kta) w radianach. Do konwersji miary kta moemy uy metody toRadians() z klasy Math. import java.util.Scanner; public class Z11 3b { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Podaj dugo przyprostoktnej, a = "); double a = input.nextDouble(); System.out.print("Podaj miar kta ostrego (°), alfa = ");
Rozdzia 6. i Rozwizania zada
155
double alfa = input.nextDouble(); double c = a/Math.sin(Math.toRadians(alfa)); System.out.printf("Dugo przeciwprostoktnej c = %.3f\n", c); input.close(); } }
Zadanie 11.4. Z11 4.java Liczba bitów zostaa ograniczona do 31 ze wzgldu na zastosowanie typu zmiennych int i klasy Integer. Mona liczb bitów zwikszy do 63, stosujc zmienne typu long i klas opakowujc Long. Wykorzystujc metod next(), odczytujemy ze skanera kolejny token i nastpnie zamieniamy go na liczb cakowit. Metoda parseInt() z klasy Integer umoliwia okrelenie podstawy systemu liczbowego (drugi parametr). Po odkodowaniu (z systemu binarnego) dwóch liczb a i b moemy obliczy ich sum a+b, któr nastpnie zamieniamy na cig znaków reprezentujcy jej posta binarn Integer. toBinaryString(a+b). import java.util.Scanner; public class Z11 4 { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("Podaj dwie liczby w systemie binarnym (do 31 bitów)"); System.out.print("a = "); String str = input.next(); int a = Integer.parseInt(str, 2); System.out.print("b = "); str = input.next(); int b = Integer.parseInt(str, 2); str = Integer.toBinaryString(a+b); System.out.println("a+b = "+str); input.close(); } }
Moemy zmieni podstaw systemu liczbowego w skanerze, uywajc metody useRadix(), a nastpnie odczytywa liczby cakowite zapisane w systemie liczbowym o tej podstawie. input.useRadix(2); System.out.print("a = "); int a = input.nextInt(); System.out.print("b = "); int b = input.nextInt();
Zadanie 11.5. Z11 5.java Uamek zwyky wprowadzamy z klawiatury jako acuch znaków (np. 23/45), w którym licznik i mianownik (liczby cakowite) oddzielone s symbolem / (bez odstpów). Zakadamy, e uytkownik poprawnie wprowadzi dane. Wczytujemy token ze skanera input i zamieniamy na liczby cakowite a i b czci acucha przed znakiem / i po nim. Aby obliczy warto dziesitn uamka, podzielimy licznik przez mianownik a/b. Takie dzielenie daoby jednak wynik cakowity, wic naleaoby co najmniej jedn z tych liczb skonwertowa (rzutowa) na typ zmiennoprzecinkowy double (lub
156
Programowanie w jzyku Java float) i uzyska wynik zmiennoprzecinkowy, np. (double)a/b lub a/(double)b. Po-
niewa dodatkowo potrzebujemy zamieni ten uamek na procent, to mnoymy wynik przez 100. Stosujc sta w postaci zmiennoprzecinkowej 100.0 (double) lub 100.0f (float) i odpowiedni kolejno dziaa, uzyskamy waciwy rezultat (bez potrzeby jawnego rzutowania a lub b na typ zmiennoprzecinkowy): 100.0*a/b lub 100.0f*a/b. Mnoenie i dzielenie maj ten sam priorytet, ale dziaania w tym przypadku wykonywane s od strony lewej do prawej — mnoenie da wynik zmiennoprzecinkowy, wic wynik pó niejszego dzielenia równie bdzie liczb zmiennoprzecinkow. import java.util.Scanner; public class Z11 5 { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Podaj uamek zwyky (np. 23/45): "); String u = input.next(); int a = Integer.parseInt(u.substring(0, u.indexOf("/"))); int b = Integer.parseInt(u.substring(u.indexOf("/")+1)); System.out.printf("%d/%d = %.1f%%%n", a, b, 100.0*a/b); input.close(); } }
Zadanie 11.6. Z11 6.java
acuch s zawiera dane tekstowe — cztery tokeny oddzielone odstpami (dwa sowa, liczb cakowit i liczb dziesitn). String s = "Jan Nowak 150 25,3"; Scanner input = new Scanner(s);
Podajc acuch s jako parametr konstruktora, otrzymamy obiekt input umoliwiajcy odczytanie danych z acucha znaków. Stosujc metod next(), odczytamy sowa (Jan i Nowak), potem odczytamy liczb cakowit 150 (metod nextInt()) i liczb dziesitn (zmiennoprzecinkow) 25,3 (metod nextDouble()). Majc dane, wykonamy obliczenia i sformuujemy odpowied . Na koniec zamykamy skaner (input.close()). import java.util.Scanner; public class Z11 6 { public static void main(String[] args) { String s = "Jan Nowak 150 25,3"; Scanner input = new Scanner(s); String s1 = input.next(); String s2 = input.next(); int a = input.nextInt(); double b = input.nextDouble(); System.out.printf("%s %s %.2f\n", s2, s1, a*b); input.close(); } }
Zadanie 11.7. Z11 7.java Rozwizanie tego zadania jest podobne do rozwizania zadania 11.6. Istotn rónic jest ródo danych — tym razem dane odczytamy z pliku. Dodatkowo importujemy dwie klasy z pakietu java.io, klas IOException (wyjtki operacji wejcia-wyjcia,
Rozdzia 6. i Rozwizania zada
157
które poznasz dokadniej w dalszych rozdziaach) i klas File. W nagówku metody main dopisujemy informacj o licie wyjtków (throws IOException), które mog zosta wygenerowane podczas operacji z plikami. Obsug tych wyjtków zajmie si wirtualna maszyna Javy, wywoujca metod main. Sytuacja ta zostanie omówiona dokadniej na dalszych stronach. Teraz skoncentrujmy uwag na wykorzystaniu klasy Scanner do odczytywania danych z pliku. Tworzymy obiekt f klasy File skojarzony z plikiem dane.txt (File f = new File("dane.txt")) i obiekt input klasy Scanner do odczytywania danych z pliku (Scanner input = new Scanner(f)). Reszta kodu pozostaje bez zmian. import java.io.File; import java.io.IOException; import java.util.Scanner; public class Z11 7 { public static void main(String[] args) throws IOException { File f = new File("dane.txt"); Scanner input = new Scanner(f); String s1 = input.next(); String s2 = input.next(); int a = input.nextInt(); double b = input.nextDouble(); System.out.printf("%s %s %.2f\n", s2, s1, a*b); input.close(); } }
12. Operacje na tekstach — klasy StringBuffer i StringBuilder Zadanie 12.1. Z12 1.java To zadanie i dwa zadania nastpne (12.2 i 12.3) traktujemy jako pretekst do przedstawienia wybranych metod klasy StringBuilder (lub StringBuffer). Wykresem równania y
ax 2 bx c, a z 0 jest parabola o wierzchoku §¨ b , ' ·¸ , © 2a 4 a ¹
gdzie ' b 4ac . Pobieramy dane (wspóczynniki trójmianu) z konsoli, zakadajc, e uytkownik poda poprawne liczby (a róne od zera), i obliczamy wyrónik trójmianu (delta). Pozostae obliczenia wykonamy podczas budowania odpowiedzi. 2
Tworzymy obiekt point klasy StringBuilder zawierajcy acuch znaków "Wierzchoek paraboli (", czyli pocztek odpowiedzi. StringBuilder point = new StringBuilder("Wierzchoek paraboli (");
Stosujc metod append(), dodamy na kocu acucha znaków (obiektu point) kolejno: warto pierwszej wspórzdnej wierzchoka paraboli (–b/(2*a)), przecinek i odstp (", "), warto drugiej wspórzdnej wierzchoka paraboli (–delta/(4*a)) i nawias
158
Programowanie w jzyku Java
zamykajcy par wspórzdnych punktu (")"). Zwrómy uwag na uycie nawiasów w mianownikach wyrae, wyznaczajcych waciw kolejno wykonywania dziaa (mnoenia i dzielenia). import java.util.Scanner; public class Z12 1 { public static void main(String args[]) { System.out.println("Obliczanie wspórzdnych wierzchoka paraboli"); System.out.print("Podaj wspóczynniki trójmianu kwadratowego oddzielone odstpami: "); double a, b, c; /* Wczytywanie danych z konsoli */ Scanner input = new Scanner(System.in); a = input.nextDouble(); b = input.nextDouble(); c = input.nextDouble(); input.close(); /* Obliczenia i budowanie odpowiedzi */ double delta = b*b 4*a*c; StringBuilder point = new StringBuilder("Wierzchoek paraboli ("); point.append( b/(2*a)).append(", "). append( delta/(4*a)).append(")"); System.out.println(point); } }
Do sformuowania odpowiedzi moemy uy operatora konkatenacji (czenia tekstów +). Kompilator w tym przypadku równie wykorzysta metody klasy StringBuilder. String s = "Wierzchoek paraboli ("+( b/(2*a))+", "+( delta/(4*a))+")"; System.out.println(s);
1. Zadanie moemy rozwiza w taki sam sposób, zastpujc klas StringBuilder klas StringBuffer. Klasy maj identyczne metody, jednak klasa String Builder jest nowsza. Po klas StringBuffer signiemy wtedy, gdy niezbdne bdzie buforowanie operacji na acuchu znaków. 2. Odpowied moemy sformuowa i sformatowa , stosujc metod printf() lub format() do wywietlania wyniku: System.out.printf("Wierzchoek paraboli(%.2f, %.2f)", delta/(4*a));
b/(2*a),
lub metod format() do budowania acucha: String s = String.format(("Wierzchoek paraboli(%.2f, %.2f)", delta/(4*a));
b/(2*a),
Zadanie 12.2. Z12 2.java Ponownie rozwizujemy zadanie 12.1, stosujc inny sposób budowania odpowiedzi. Zaczynamy od acucha (obiekt point klasy StringBuilder) zoonego z pary nawiasów okrgych, przecinka i odstpu "(, )" — cznie cztery znaki o indeksach 0, 1, 2 i 3.
Rozdzia 6. i Rozwizania zada
159
Przed znakiem o indeksie 3 (midzy odstpem i nawiasem zamykajcym) wstawiamy warto drugiej wspórzdnej wierzchoka paraboli point.insert(3, (-delta/(4*a))). Konwersja zmiennoprzecinkowego typu wartoci wyraenia na acuch znaków wykonywana jest przez metod insert. Nastpnie przed znakiem o indeksie 1 (midzy nawiasem otwierajcym i przecinkiem) wstawiamy warto pierwszej wspórzdnej wierzchoka paraboli point.insert(1, -b/(2*a)). Obie te czynnoci moemy zapisa cznie, w jednym wierszu: point.insert(3, ( delta/(4*a))).insert(1,
b/(2*a));
Bardzo wana jest kolejno wstawiania tych liczb do acucha pocztkowego "(, )". /* Obliczenia i budowanie odpowiedzi */ double delta = b*b 4*a*c; StringBuilder point = new StringBuilder("(, )"); point.insert(3, ( delta/(4*a))).insert(1, b/(2*a)); System.out.println("Wierzchoek paraboli: "+point);
Pozostaa cz kodu jest podobna jak w zadaniu 12.1.
Zadanie 12.3. Z12 3.java Jeszcze raz rozwizujemy zadanie 12.1, stosujc tym razem metod replace() (zastp) z klasy StringBuilder. Na pocztek budujemy acuch (obiekt point klasy String Builder) o postaci "(#1, #2)". Wystpujce w acuchu symbole #1 i #2 wskazuj miejsca, w których umiecimy wyniki oblicze. Metoda replace() ma trzy parametry, dwa indeksy okrelajce zakres zastpowanych znaków i podstawiany w to miejsce acuch znaków (dugo tego acucha nie jest ograniczona przez zakres zastpowanych znaków). Liczby przed wstawieniem musimy zamieni na acuchy znaków. Najpierw znajdujemy pooenie (indeks pierwszego znaku) symbolu "#1" w obiekcie point (start = point.indexOf("#1")), a nastpnie zamieniamy dwa znaki (od indeksu start do indeksu start+1) acuchem znaków utworzonym z wartoci pierwszej wspórzdnej wierzchoka paraboli (String.valueOf(-b/(2*a))). Podobnie zamieniamy symbol "#2" na odpowiedni warto. /* Obliczenia i budowanie odpowiedzi */ double delta = b*b 4*a*c; StringBuilder point = new StringBuilder("(#1, #2)"); int start = point.indexOf("#1"); point.replace(start, start+1, String.valueOf( b/(2*a))); start = point.indexOf("#2"); point.replace(start, start+1, String.valueOf( delta/(4*a))); System.out.println("Wierzchoek paraboli: "+point);
W drugim wariancie rozwizania proponujemy inny sposób zamiany liczby zmiennoprzecinkowej na acuch znaków (new Double(-b/(2*a)).toString()). /* Obliczenia i budowanie odpowiedzi */ double delta = b*b 4*a*c; StringBuilder point = new StringBuilder("(#1, #2)"); int start = point.indexOf("#1"); point.replace(start, start+1, new Double( b/(2*a)).toString()); start = point.indexOf("#2");
160
Programowanie w jzyku Java point.replace(start, start+1, new Double( delta/(4*a)).toString()); System.out.println("Wierzchoek paraboli: "+point);
Kolejny wariant moe wykorzysta waciwoci operatora konkatenacji (+): point.replace(start, start+1, ""+( b/(2*a)));
Zadanie 12.4. Z12 4.java Z konsoli odczytujemy liczb cakowit dodatni n (nie sprawdzamy poprawnoci danych wprowadzonych przez uytkownika) i tworzymy obiekt liczba klasy String Builder, reprezentujcy pusty acuch znaków. Po wywoaniu metod liczba.append(n).reverse() obiekt liczba zawiera cyfry liczby n, zapisane w odwrotnej kolejnoci. W odpowiednim momencie zamienimy zawarto obiektu na liczb cakowit Integer.parseInt(liczba.toString()). Drugi obiekt wynik klasy StringBuilder i metod append() wykorzystamy do skonstruowania odpowiedzi. import java.util.Scanner; public class Z12 4 { public static void main(String args[]) { System.out.print("Podaj liczb cakowit dodatni: "); Scanner input = new Scanner(System.in); int n = input.nextInt(); input.close(); StringBuilder liczba = new StringBuilder(); liczba.append(n).reverse(); StringBuilder wynik = new StringBuilder(); wynik.append(n).append(" ").append(liczba).append(" = "); wynik.append(n Integer.parseInt(liczba.toString())); System.out.println(wynik); } }
Zadanie 12.5. Z12 5.java Wspórzdne wektora wprowadzamy w postaci pary liczb oddzielonych przecinkiem i zawartych w nawiasie prostoktnym, np. [2.5, –3]. Z konsoli wczytujemy wiersz tekstu i usuwamy (metoda trim()) zbdne biae znaki z pocztku i koca acucha String wekt = input.nextLine().trim(). Zakadamy, e otrzymany acuch zawiera poprawn posta wspórzdnych wektora, i tworzymy nowy obiekt, na którym wykonamy dalsze przeksztacenia (StringBuilder tmp = new StringBuilder(wekt)). Z acucha usuwamy nawiasy prostoktne, czyli pierwszy (tmp.deleteCharAt(0)) i ostatni znak (tmp.deleteCharAt(tmp.length()-1)). Nastpnie odszukujemy pooenie przecinka oddzielajcego wspórzdne wektora (int poz = tmp.indexOf(",")) i rozdzielamy acuch na dwa podacuchy, które konwertujemy na zmiennoprzecinkowe wartoci wspórzdnych wektora (liczby zapisane s z kropk dziesitn lub w postaci cakowitej):
Rozdzia 6. i Rozwizania zada
161
double a = Double.parseDouble(tmp.substring(0, poz)); double b = Double.parseDouble(tmp.substring(poz+1));
Na koniec pozostaje obliczenie dugoci wektora ze wzoru u
a 2 b 2 (Math.sqrt
(a*a+b*b)) i sformuowanie odpowiedzi. import java.util.Scanner; public class Z12 5 { public static void main(String args[]) { System.out.print("Podaj wspórzdne wektora (w postaci [a, b]): "); Scanner input = new Scanner(System.in); String wekt = input.nextLine().trim(); input.close(); StringBuilder tmp = new StringBuilder(wekt); /* Usuwamy pierwszy i ostatni znak, czyli nawiasy prostoktne. */ tmp.deleteCharAt(0).deleteCharAt(tmp.length() 1); /* Znajdujemy pozycj przecinka midzy liczbami. */ int poz = tmp.indexOf(","); /* Odczytujemy wartoci liczb. */ double a = Double.parseDouble(tmp.substring(0, poz)); double b = Double.parseDouble(tmp.substring(poz+1)); /* Obliczamy i wywietlamy dugo wektora. */ System.out.println("Dugo wektora "+wekt+" jest równa "+ Math.sqrt(a*a+b*b)); } }
Do pobrania wspórzdnych wektora z acucha znaków moemy wykorzysta metod split() z klasy String. W tym celu tworzymy tablic acuchów temp[], konwertujemy obiekt tmp na acuch znaków i wywoujemy metod split(), podajc przecinek jako separator — ",": String temp[] = tmp.toString().split(",");
Nastpnie odczytujemy (z tablicy) wartoci wspórzdnych wektora: double a = Double.parseDouble(temp[0]); double b = Double.parseDouble(temp[1]);
Pozostaa cz kodu pozostaje bez zmian. Stosujc metody substring() i split(), moemy zrezygnowa z uycia obiektu tmp klasy StringBuilder: String temp[] = wekt.substring(1, wekt.length() 1).split(",");
Oczywicie dane musz by wprowadzane zgodnie z przyjt umow.
Zadanie 12.6. Z12 6.java Zadanie to rozwizujemy podobnie jak zadanie 12.5. Istotna rónica polega na tym, e mamy trzy wspórzdne oddzielone dwoma przecinkami. Pooenie tych przecinków (pierwszego i ostatniego) ustalimy, uywajc metod indexOf() i lastIndexOf().
162
Programowanie w jzyku Java import java.util.Scanner; public class Z12 6 { public static void main(String args[]) { System.out.print("Podaj wspórzdne wektora (w postaci [a, b, c]): "); Scanner input = new Scanner(System.in); String wekt = input.nextLine().trim(); input.close(); StringBuilder tmp = new StringBuilder(wekt); /* Usuwamy pierwszy i ostatni znak, czyli nawiasy prostoktne. */ tmp.deleteCharAt(0).deleteCharAt(tmp.length() 1); /* Znajdujemy pozycje przecinków midzy liczbami. */ int poz1 = tmp.indexOf(","); int poz2 = tmp.lastIndexOf(","); /* Odczytujemy wartoci liczb. */ double a = Double.parseDouble(tmp.substring(0, poz1)); double b = Double.parseDouble(tmp.substring(poz1+1, poz2)); double c = Double.parseDouble(tmp.substring(poz2+1)); /* Obliczamy i wywietlamy dugo wektora. */ System.out.println("Dugo wektora "+wekt+" jest równa "+ Math.sqrt(a*a+b*b+c*c)); } }
Podobnie jak w rozwizaniu zadania 12.5, do wyznaczenia wspórzdnych wektora moemy zastosowa metod split() z klasy String: /* Pomijamy pierwszy i ostatni znak, czyli nawiasy prostoktne, i dzielimy acuch znaków na czci rozdzielone przecinkiem. */ String temp[] = wekt.substring(1, wekt.length() 1).split(","); /* Odczytujemy wartoci liczb - wspórzdnych wektora. */ double a = Double.parseDouble(temp[0]); double b = Double.parseDouble(temp[1]); double c = Double.parseDouble(temp[2]);
13. Instrukcje warunkowe i instrukcja selekcji Zadanie 13.1. Z13 1.java Wprowadzone imi jest przechowywane w obiekcie str klasy String. Odpowied skonstruujemy jako obiekt name klasy StringBuilder — StringBuilder name = new StringBuilder(str);. W zmiennej z przechowujemy ostatni znak imienia — char z = name.charAt(name.length()-1);. Do imienia (name) dodajemy sowo " jest " wraz z odstpami przed sowem i za sowem — name.append(" jest ");. Na koniec uzupeniamy odpowied sowem okrelajcym pe osoby, w zalenoci od tego, jak warto ma wyraenie logiczne z == 'a'. Jeli wyraenie ma warto true (ostatni liter imienia jest a), to do odpowiedzi dodajemy tekst "kobiet.", w przeciwnym razie dodajemy tekst "mczyzn.".
Rozdzia 6. i Rozwizania zada
163
import java.util.Scanner; public class Z13 1 { public static void main(String args[]) { System.out.print("Podaj imi: "); Scanner input = new Scanner(System.in); String str = input.next(); input.close(); StringBuilder name = new StringBuilder(str); char z = name.charAt(name.length() 1); name.append(" jest "); if (z == 'a') name.append("kobiet."); else name.append("mczyzn."); System.out.println(name); } }
Zadanie 13.2. Z13 2.java Jeeli wczytana warto zmiennej a (dugo boku kwadratu) jest dodatnia, to wykonujemy obliczenia i wywietlamy wynik. W kolejnej instrukcji warunkowej badamy, czy podana dugo boku jest mniejsza lub równa 0 — jeli tak jest, to wywietlamy komunikat o bdnych danych. import java.util.Scanner; public class Z13 2 { public static void main(String args[]) { System.out.println("Obliczanie pola powierzchni i obwodu kwadratu"); Scanner input = new Scanner(System.in); System.out.print("Podaj dugo boku, a = "); double a = input.nextDouble(); input.close(); if (a > 0) { double pole = a*a; double obwod = 4*a; System.out.println("Pole powierzchni P = "+pole); System.out.println("Obwód kwadratu L = "+obwod); } if (a 0 i a 0) { double pole = a*a; double obwod = 4*a; System.out.println("Pole powierzchni P = "+pole); System.out.println("Obwód kwadratu L = "+obwod); } else System.out.println("Bd! Dugo boku ma by liczb dodatni.");
164
Programowanie w jzyku Java
Zadanie 13.3. Z13 3.java Po wprowadzeniu danych tworzymy obiekt wynik klasy StringBuilder. Stanowicy odpowied acuch znaków skada si z nawiasów < i > dla przedziau domknitego lub { i } w przypadku zbioru jednoelementowego (przypadek a jest równe b). Wartoci zmiennych a i b w przypadku przedziau powinny by wprowadzone do wyniku w porzdku rosncym. Mamy zatem trzy przypadki: Przypadek
Budowanie odpowiedzi
a < b
wynik.append("");
b < a
wynik.append("");.
a == b
wynik.append("{").append(a).append("}");
Przedstawiona sytuacja wymaga zbudowania trzech instrukcji warunkowych lub zastosowania tzw. zagniedenia instrukcji warunkowej. import java.util.Scanner; public class Z13 3 { public static void main(String args[]) { System.out.println("Podaj dwie liczby a i b:"); Scanner input = new Scanner(System.in); System.out.print("a = "); double a = input.nextDouble(); System.out.print("b = "); double b = input.nextDouble(); input.close(); StringBuilder wynik = new StringBuilder(); if (a < b) wynik.append(""); else if (b < a) wynik.append(""); else wynik.append("{").append(a).append("}"); wynik.insert(0, "Zbiór wszystkich liczb zawartych pomidzy a i b, X = "); System.out.println(wynik); } }
Zadanie 13.4. Z13 4.java Po wprowadzeniu wartoci wspóczynnika a trójmianu ax 2 bx c sprawdzamy podan warto. Jeli a jest zerem, to wywietlamy komunikat skierowany do standardowego strumienia bdów System.err.println(...) i zamykamy aplikacj System. exit(0). Gdy a jest róne od zera, wczytujemy pozostae wspóczynniki trójmianu ' 4a
b 2 4ac 4a znaku wspóczynnika a i wartoci q:
(b i c) i obliczamy q
4ac b 2 . Zbiór wartoci funkcji zaley od 4a
Rozdzia 6. i Rozwizania zada
Znak a a > 0 a < 0
Zbiór wartoci
q, f ) (f, q
165
Budowanie odpowiedzi wynik.append("").insert(6, q);
import java.util.Scanner; public class Z13 4 { public static void main(String args[]) { System.out.println("Podaj wspóczynniki funkcji kwadratowej:"); Scanner input = new Scanner(System.in); System.out.print("a = "); double a = input.nextDouble(); if (a == 0) { System.err.println("a = 0, to nie jest funkcja kwadratowa."); System.exit(0); } System.out.print("b = "); double b = input.nextDouble(); System.out.print("c = "); double c = input.nextDouble(); input.close(); double q = (4*a*c b*b)/(4*a); StringBuilder wynik = new StringBuilder(); if (a > 0) wynik.append("").insert(6, q); System.out.println("Zbiór wartoci: "+wynik); } }
Zadanie 13.5. Z13 5.java Wczytywanie danych (wspóczynników trójmianu) zorganizujemy tak, jak w rozwizaniu zadania 13.4. Nastpnie obliczymy wspórzdne p i q wierzchoka paraboli bdcej wykresem tej funkcji kwadratowej. double p = b/(2*a); double q = (4*a*c b*b)/(4*a);
W budowanej odpowiedzi umiecimy symbole #1 i #2. W miejsce tych symboli podstawimy pó niej odpowiednie sowa "rosnca" i "malejca", w zalenoci od znaku wspóczynnika a. StringBuilder wynik = new StringBuilder(); wynik.append("Funkcja jest #1 w przedziale ( oo, ").append(p); wynik.append("> i #2 w przedziale 360) throw new IllegalArgumentException("Liczba stopni poza zakresem."); x = deg/180.0*Math.PI; } /** Tworzy nowy obiekt Angle reprezentujcy kt o podanej * liczbie stopni i minut. * @param deg liczba stopni, liczba cakowita typu int * z przedziau , * @param min liczba minut, liczba cakowita typu int
Rozdzia 7. i Rozwizania zada
273
* z przedziau . * @throws IllegalArgumentException, gdy liczba stopni nie mieci si * w przedziale , * @throws IllegalArgumentException, gdy liczba minut nie mieci si * w przedziale . */ public Angle(int deg, int min) { if (deg < 0 || deg > 360) throw new IllegalArgumentException("Liczba stopni poza zakresem."); if (min < 0 || min > 60) throw new IllegalArgumentException("Liczba minut poza zakresem."); x = (deg+min/60.0)/180.0*Math.PI; } /** Tworzy nowy obiekt Angle reprezentujcy kt o podanej * liczbie stopni, minut i sekund. * @param deg liczba stopni, liczba cakowita typu int * z przedziau , * @param min liczba minut, liczba cakowita typu int * z przedziau , * @param sek liczba sekund, liczba cakowita typu int * z przedziau . * @throws IllegalArgumentException, gdy liczba stopni nie mieci si * w przedziale , * @throws IllegalArgumentException, gdy liczba minut nie mieci si * w przedziale , * @throws IllegalArgumentException, gdy liczba sekund nie mieci si * w przedziale . */ public Angle(int deg, int min, int sek) { if (deg < 0 || deg > 360) throw new IllegalArgumentException("Liczba stopni poza zakresem."); if (min < 0 || min > 60) throw new IllegalArgumentException("Liczba minut poza zakresem."); if (sek < 0 || sek > 60) throw new IllegalArgumentException("Liczba sekund poza zakresem."); x = (deg+min/60.0+sek/3600.0)/180.0*Math.PI; }
Obliczenia przykadowe podamy dla kilku któw, np. 15°, 22°30' i 10°30" (zero minut pominlimy w tym zapisie, ale musimy przekaza do metody warto 0 jako drugi parametr). /** Zadanie Z21.4 */ public class Z21 4 { public static void main(String args[]) { Angle alfa = new Angle(15); System.out.print("alfa = "+alfa); System.out.println(" = "+alfa.radian()+" rad"); alfa = new Angle(22, 30); System.out.print("alfa = "+alfa); System.out.println(" = "+alfa.radian()+" rad"); alfa = new Angle(10, 0, 30);
274
Programowanie w jzyku Java System.out.print("alfa = "+alfa); System.out.println(" = "+alfa.radian()+" rad"); } }
Zadanie 21.5. Z21 5.java, Angle.java Wyznaczamy pooenie znaków stopnia (int p = st.indexOf("\u00B0")), minuty (int q = st.indexOf("\'")) i sekundy ktowej (int r = st.indexOf("\"")) w cigu wejciowym. Otrzymamy indeksy wskazujce pooenie tych znaków w acuchu st lub warto -1, gdy znak nie wystpuje w acuchu. Na tej podstawie moemy wstpnie oceni poprawno cigu znaków. Pominiemy t analiz i spróbujemy wyznaczy liczb stopni, minut i sekund, konwertujc odpowiedni podcig na liczb cakowit. Czynnoci te ujmujemy w bloku try {...} i przechwytujemy ewentualne wyjtki. Przyczyn zgoszenia wyjtku moe by brak jednego z symboli (°, ' lub "), co spowoduje podanie parametru -1 do metody substring() i wygenerowanie wyjtku java. lang.StringIndexOutOfBoundsException. Drugim powodem zgoszenia wyjtku moe by bd w zapisie liczb, np. 2O°30'15" (litera O zamiast cyfry 0) — metoda parseInt() zgosi wyjtek java.lang.NumberFormatException. Przechwycimy te wyjtki i zastpimy je wyjtkiem throw new IllegalArgumentException(st). Jeli dane wejciowe s poprawne, to moemy zamieni odczytane wartoci deg, min i sek na miar kta w radianach i podstawi uzyskan warto do pola x obiektu: this.x = (deg+min/60.0+sek/3600.0)/180.0*Math.PI;. public Angle(String st) { int deg, min, sek; int p = st.indexOf("\u00B0"); // stopie int q = st.indexOf("\'"); // minuta ktowa int r = st.indexOf("\""); // sekunda ktowa try { deg = Integer.parseInt(st.substring(0, p)); min = Integer.parseInt(st.substring(p+1, q)); sek = Integer.parseInt(st.substring(q+1, r)); } catch (Exception e) { throw new IllegalArgumentException(st); } this.x = (deg+min/60.0+sek/3600.0)/180.0*Math.PI; }
Ta wersja konstruktora ma co najmniej trzy wady: 1. Nie dopuszcza skróconych postaci danych, np. 25°15' lub 33° (naley
napisa 25°15'0" lub 33°'0'0"). 2. Pozwala na dziwne postacie danych, np. 13°–13'17" (ujemna liczba minut)
lub 1°360'99" (zbyt dua liczba minut i sekund) — dane te zostan zinterpretowane jako 12°47'17" (od 13° odjto 13' i wyszo 12°47') lub 7°1'39" (360' = 6°, 99" = 1'39" — ogólny bilans si zgadza). 3. le interpretuje ujemn miar kta, np. 22°30'0" = 0.39269908169872414
rad, ale –22°30'0" zostanie zinterpretowane jako –21°30'0" = –0.3752457891787809 rad.
Rozdzia 7. i Rozwizania zada
275
Spróbujemy te wady wyeliminowa. Zainicjowanie zmiennej sek = 0 i dodanie instrukcji warunkowej: if (r > 0) sek = Integer.parseInt(st.substring(q+1, r));
pozwoli pomija w cigu danych liczb sekund i symbol sekundy ("). Dopuszczalna jest posta danych bez sekund, np. 22°30'. Zainicjujmy dodatkowo min = 0 i dodajmy instrukcje warunkowe: if (q > 0) { min = Integer.parseInt(st.substring(p+1, q)); if (r > 0) sek = Integer.parseInt(st.substring(q+1, r)); }
Teraz moemy wprowadza dane w postaci 22°15'37", 22°15' lub 22°. Nie mona pomin minut, gdy wystpuj sekundy — kt 15°30" musimy zapisa jako 15°0'30" — oraz nie mona pomin stopni — musimy pisa 0°45' zamiast 45'. To ju nie jest zbyt dua niedogodno. Liczba minut i liczba sekund powinny przyjmowa wartoci wycznie dodatnie z zakresu od 0 do 59. Fakt ten sprawdzimy przed przeliczaniem podanej miary kta na radiany: if ((min < 0) || (min > 59) || (sek < 0) || (sek > 59)) throw new IllegalArgumentException(st);
i zgosimy wyjtek, gdy dane nie bd poprawne. Problem ujemnej miary kta moemy rozwiza tak: boolean znak =false; if (deg < 0) { znak = true; deg = deg; } this.x = (deg+min/60.0+sek/3600.0)/180.0*Math.PI; if (znak) this.x = this.x;
Po tych zmianach kod konstruktora bdzie wyglda nastpujco: public Angle(String st) { int deg, min = 0, sek = 0; int p = st.indexOf("\u00B0"); // stopie int q = st.indexOf("\'"); // minuta ktowa int r = st.indexOf("\""); // sekunda ktowa try { deg = Integer.parseInt(st.substring(0, p)); if (q > 0) { min = Integer.parseInt(st.substring(p+1, q)); if (r > 0) sek = Integer.parseInt(st.substring(q+1, r)); } } catch (Exception e) { throw new IllegalArgumentException(st); }
276
Programowanie w jzyku Java if ((min < 0) || (min > 59) || (sek < 0) || (sek > 59)) throw new IllegalArgumentException(st); boolean znak =false; if (deg < 0) { znak = true; deg = deg; } this.x = (deg+min/60.0+sek/3600.0)/180.0*Math.PI; if (znak) this.x = this.x; }
Dziaanie konstruktora moemy sprawdzi dla kilku przykadowych acuchów znaków (poprawnych lub bdnych). /** Zadanie Z21.5 */ public class Z21 5 { public static void main(String args[]) { String[] angles = { "15°30'27\"", "43°52'", "22°", " 22°30'", "22°30'", "35'30\"", "1°65'", "abc", "36", "15° 30'" }; Angle alfa = null; for(String a: angles) { try { alfa = new Angle(a); System.out.print("alfa = "+alfa); System.out.println(" = "+alfa.radian()+" rad"); } catch (IllegalArgumentException e){ System.out.println("Bdne dane: "+a); } } } }
Zadanie 21.6. Z21 6.java, Angle.java Funkcje trygonometryczne s funkcjami okresowymi w swojej dziedzinie (zbiorze liczb rzeczywistych). Funkcje odwrotne moemy okreli w sposób jednoznaczny wycznie w wybranych przedziaach. Zwykle przyjmujemy takie dziedziny funkcji odwrotnych:
S S
, 2 2
dla funkcji arcus
S S sinus i arcus cosecans, 0, S dla arcus cosinus i arcus secans, §¨ , ·¸ dla funkcji
arcus tangens i 0, S dla arcus cotangens.
©
2 2¹
W obliczeniach wykorzystamy metody z klasy Math: asin() (arcus sinus), acos() (arcus cosinus) i atan() (arcus tangens) oraz znane waciwoci funkcji trygonometrycznych i funkcji do nich odwrotnych. Funkcje sinus i cosinus przyjmuj wartoci z przedziau 1, 1 , wic argumentem funkcji odwrotnej mog by wycznie liczby z tego przedziau. Funkcjom arcus sinus i arcus cosinus odpowiadaj metody:
Rozdzia 7. i Rozwizania zada
277
public void setOfSin(double x) { if (x >= 1 && x = 1 && x 1 && x < 1) throw new IllegalArgumentException(); else this.x = Math.acos(1/x); } public void setOfCsc(double x) { if (x > 1 && x < 1) throw new IllegalArgumentException(); else this.x = Math.asin(1/x); }
Tworzc program demonstrujcy dziaanie tych metod wybieramy takie wartoci argumentu x, dla których wywietlone wyniki bd atwe do zweryfikowania. /** Zadanie Z21.6 */ public class Z21 6 { public static void main(String args[]) { Angle alfa = new Angle(0);; double x = Math.sqrt(2)/2; alfa.setOfSin(x); System.out.printf("sin x = %.6f, ", x); System.out.println("alfa = "+alfa); alfa.setOfCos( x);
278
Programowanie w jzyku Java System.out.printf("cos x System.out.println("alfa x = 1; alfa.setOfTan(x); System.out.printf("tan x System.out.println("alfa alfa.setOfCot(x); System.out.printf("cot x System.out.println("alfa x = 2/Math.sqrt(3); alfa.setOfSec(x); System.out.printf("sec x System.out.println("alfa alfa.setOfCsc(x); System.out.printf("csc x System.out.println("alfa
= %.6f, ", = "+alfa);
x);
= %.6f, ", x); = "+alfa); = %.6f, ", x); = "+alfa);
= %.6f, ", x); = "+alfa); = %.6f, ", x); = "+alfa);
} }
We my znan warto sin 60q sin csc 60q
csc
S
2
3
3
sec
S 6
S 3
3 2
cos
S 6
cos 30q . Std moemy obliczy
sec 30q . Wykonujc powyszy program, uzyskamy tak
odpowied (dla metod setOfSec() i setOfCsc()), zgodn z oczekiwaniem: sec x = 1,154701, alfa = 30° csc x = 1,154701, alfa = 60°
Zadanie 21.7. Z21 7.java, Angle.java W klasie Math mamy metod atan2() z dwoma parametrami x i y, które s wspórzdnymi punktu P w prostoktnym ukadzie wspórzdnych. Wspórzdne tego punktu moemy zapisa w ukadzie biegunowym w postaci r , T , gdzie x r cosT i y r sin T . Do obliczenia miary kta T suy wanie metoda atan2(). Zwracany kt naley do przedziau od S do S (miara kta ma znak parametru y). W metodzie korygujemy ten wynik dla ujemnych wartoci parametru y, dodajc 2S (podwójny okres funkcji tangens). Ostateczny wynik naley do przedziau od 0 do 2S (od 0° do 360°). public void setOfPoint(double x, double y) { if (x == 0 && y == 0) throw new IllegalArgumentException(); if (y >= 0) this.x = Math.atan2(y, x); else this.x = 2*Math.PI+Math.atan2(y, x); }
Przykad dziaania metody setOfPoint(): /** Zadanie Z21.7 */ public class Z21 7 { public static void main(String args[]) { Angle a = new Angle(0); double x = 5.0, y = 5.0;
Rozdzia 7. i Rozwizania zada
279
a.setOfPoint(x, y); System.out.printf("P(%.2f, %.2f), ", x, y); System.out.println("kt "+a.degree()+"\u00B0"); x = 0.0; y = 5.0; System.out.printf("P(%.2f, %.2f), ", x, y); a.setOfPoint(x, y); System.out.println("kt "+a.degree()+"\u00B0"); } }
Zadanie 21.8. Z21 8.java, Angle.java Kod konstruktora bdzie podobny do kodu metody setOfPoint() przedstawionej w rozwizaniu zadania 21.7. public Angle(double x, double y) { if (x == 0 && y == 0) throw new IllegalArgumentException(); if (y >= 0) this.x = Math.atan2(y, x); else this.x = 2*Math.PI+Math.atan2(y, x); }
Dziaanie konstruktora pokaemy na przykadzie dwóch punktów A(3, 4) i B(-5, 0). Pomimo cakowitych wartoci wspórzdnych punktów musimy pamita o koniecznoci ich przedstawienia w postaci liczb zmiennoprzecinkowych (kompilator na podstawie typów parametrów wywoania konstruktora dobierze waciwy kod konstruktora). /** Zadanie Z21.8 */ public class Z21 8 { public static void main(String args[]) { // punkt A(4.0, 3.0) Angle a = new Angle(4.0, 3.0); System.out.println("A(4.0, 3.0), kt "+a); // punkt B(-5.0, 0.0) Angle b = new Angle( 5.0, 0.0); System.out.println("B( 5.0, 0.0), kt "+b); } }
W aktualnej postaci klasy Angle dla punktu A(4, 3) poprawne bd konstrukcje Angle a = new Angle(4.0, 3.0), Angle a = new Angle(4.0, 3) i Angle a = new Angle(4, 3.0), którym odpowiada kt 36°52'12". Natomiast konstrukcja Angle a = new Angle(4, 3) zbuduje kt 4°3', korzystajc z konstruktora Angle(int, int) pochodzcego z rozwizania zadania 21.4.
Zadanie 21.9. Z21 9.java, Angle.java We wszystkich utworzonych metodach statycznych valueOf() na podstawie parametrów wywoania utworzymy obiekt klasy Angle i zwrócimy referencj do tego obiektu. W zalenoci od typu i liczby parametrów wejciowych wykorzystamy odpowiedni konstruktor.
280
Programowanie w jzyku Java
Metoda zwraca obiekt Angle reprezentujcy kt x radianów. public static Angle valueOf(double x) { return new Angle(x); }
Metoda zwraca obiekt reprezentujcy kt o podanej cakowitej liczbie stopni. Moemy zamieni podan liczb stopni deg na radiany i wywoa podstawowy konstruktor Angle(double), znany z zadania 20.1 (nie ma kontroli zakresu dla zmiennej deg): public static Angle valueOf(int deg) { return new Angle(deg/180.0*Math.PI); }
lub wykorzysta konstruktor z zadania 21.4 (uyty konstruktor sprawdzi, czy zmienna deg mieci si w zakresie od 0° do 360°): public static Angle valueOf(int deg) { return new Angle(deg); }
Kolejne metody statyczne zbudujemy wedug tego samego schematu: public static Angle valueOf(int deg, int min) { return new Angle((deg+min/60.0)/180.0*Math.PI); } public static Angle valueOf(int deg, int min, int sek) { return new Angle((deg+min/60.0+sek/3600.0)/180.0*Math.PI); }
lub: public static Angle valueOf(int deg, int min) { return new Angle(deg, min); } public static Angle valueOf(int deg, int min, int sek) { return new Angle(deg, min, sek); }
Zamian cigu znaków (postaci xxx°yy'zz") na obiekt klasy Angle moemy zrealizowa, uywajc metody statycznej wykorzystujcej odpowiedni konstruktor: public static Angle valueOf(String st) { return new Angle(st); }
Poniewa ten konstruktor ma pewne ograniczenia (omówione w rozwizaniu zadania 21.5), moemy spróbowa rozwiza ten problem inaczej. Szczegóow analiz kodu pozostawiamy Czytelnikowi. public static Angle valueOf(String st) { int deg = 0, min = 0, sek = 0; int pst = st.indexOf("\u00B0"); if (pst == 1) { int pmin = st.indexOf("\'"); if (pmin == 1) { int psek = st.indexOf("\"");
// stopie // nie ma symbolu stopnia // minuta ktowa // nie ma symbolu minuty // sekunda ktowa
Rozdzia 7. i Rozwizania zada
281
if (psek == 1) { // nie ma symbolu sekundy throw new IllegalArgumentException(); } else // tylko sekundy sek = Integer.parseInt(st.substring(pmin+1, psek)); } else { min = Integer.parseInt(st.substring(0, pmin)); int psek = st.indexOf("\""); // sekunda ktowa if (psek != 1) sek = Integer.parseInt(st.substring(pmin+1, psek)); } } else { // jest symbol stopnia deg = Integer.parseInt(st.substring(0, pst)); int pmin = st.indexOf("\'"); // minuta ktowa if (pmin == 1) { int psek = st.indexOf("\""); // sekunda ktowa if (psek != 1) sek = Integer.parseInt(st.substring(pst+1, psek)); } else { min = Integer.parseInt(st.substring(pst+1, pmin)); int psek = st.indexOf("\""); // sekunda ktowa if (psek != 1) sek = Integer.parseInt(st.substring(pmin+1, psek)); } } return new Angle(deg, min, sek); }
W tej postaci metoda akceptuje nastpujce cigi znaków: 15°, 15°33', 15°33'25", 15°25", 33', 33'25", 25". Za bdne uznaje cigi cyfr bez jakichkolwiek symboli (tylko liczba bez znaku stopnia, minuty lub sekundy), niebdce liczbami (zawierajce litery lub inne znaki niedozwolone w zapisie liczb), oraz poprawnie zbudowane cigi znaków ze znakiem minus na pocztku, np. –22°30'. Ten ostatni przypadek wynika z ogranicze narzuconych przez uyty konstruktor (liczba stopni od 0 do 360) — kostrutor ten jednak sprawdza poprawno liczby minut i sekund, wic nie bdziemy z niego rezygnowa. Wprowadzimy poprawki rozszerzajce zakres liczby któw na wartoci ujemne od –360 do 0. Instrukcj return new Angle(deg, min, sek) zastpimy nastpujcym cigiem instrukcji: boolean minus = false; if (deg < 0) { deg = deg; minus = true; } Angle tmp = new Angle(deg, min, sek); if (minus) tmp.x = tmp.x; return tmp;
W przypadku bdnych danych metoda rzuca wyjtek IllegalArgumentException, gdy wejciowy acuch znaków nie odpowiada poprawnej mierze kta, lub NumberFormat Exception, gdy w wejciowym acuchu (pomidzy symbolami jednostek) znajduje si niepoprawna posta liczby cakowitej.
282
Programowanie w jzyku Java
Pozostaje jeszcze metoda zwracajca obiekt — kt wyznaczony przez punkt P(x, y), rodek ukadu wspórzdnych i o OX: public static Angle valueOf(double x, double y) { return new Angle(x, y); }
Dziaanie zdefiniowanych metod sprawdzimy, piszc program: /** Zadanie Z21.9 */ public class Z21 9 { public static void main(String args[]) { Angle a; a = Angle.valueOf(Math.PI/4); System.out.println("a = "+a); a = Angle.valueOf(25); System.out.println("a = "+a); a = Angle.valueOf(25, 30); System.out.println("a = "+a); a = Angle.valueOf(25, 30, 17); System.out.println("a = "+a); String[] angles = { "33°", "33°52'", "33°52'17\"", "33°30\"", "52'17\"", "17\"", "1°65'", "2o°13'", "36", "15° 30'" }; Angle alfa = null; for(String x: angles) { try { alfa = Angle.valueOf(x); System.out.print("alfa = "+alfa); System.out.println(" = "+alfa.radian()+" rad"); } catch (Exception e){ System.out.println("Bdne dane: "+x+" "+e); } } a = Angle.valueOf(0.5, Math.sqrt(3)/2); System.out.println("a = "+a); } }
Zadanie 21.10. Z21 10.java, Angle.java Dodawanie lub odejmowanie obiektów sprowadza si do wykonania odpowiedniego dziaania na polu x tych obiektów i zwrócenia wyniku. public Angle add(Angle x) { return new Angle(this.x+x.x); } public Angle sub(Angle x) { return new Angle(this.x x.x); }
Przykad ilustrujcy dziaanie metod: /** Zadanie Z21.10 */ public class Z21 10 { private static void writeln(String s, Angle x) { StringBuilder w = new StringBuilder(s);
Rozdzia 7. i Rozwizania zada
283
w.append(" = ").append(x.radian()).append(" rad"); w.append(" = ").append(x.degree()).append("\u00B0"); System.out.println(w); } public static void main(String args[]) { Angle a = new Angle(Math.PI/3); Angle b = new Angle(Math.PI/6); writeln("a", a); writeln("b", b); writeln("a+b", a.add(b)); writeln("a b", a.sub(b)); } }
Zbudowan tu metod writeln() wykorzystamy w kilku kolejnych zadaniach (kopiujc kod metody do kodu rozwizania zadania).
Zadanie 21.11. Z21 11.java, Angle.java W metodach statycznych sum() i diff() sucych do dodawania i odejmowania obiektów Angle (miar któw) wykorzystamy jeden z tych obiektów, metody add() i sub() (pokazane w rozwizaniu zadania 21.10) i drugi obiekt podany jako parametr. public static Angle sum(Angle x, Angle y) { return x.add(y); } public static Angle diff(Angle x, Angle y) { return x.sub(y); }
Przykad ilustrujcy dziaanie metod statycznych: /** Zadanie Z21.11 */ public class Z21 11 { /* Tu wstaw kod metody: writeln */ public static void main(String args[]) { Angle a = new Angle(Math.PI/2); Angle b = new Angle(Math.PI/6); writeln("a", a); writeln("b", b); writeln("a+b", Angle.sum(a, b)); writeln("a b", Angle.diff(a, b)); } }
Kod metody writeln pokazano w rozwizaniu zadania 21.11.
Zadanie 21.12. Z21 12.java, Angle.java Mnoenie miary kta (obiektu) przez liczb zmiennoprzecinkow lub cakowit (wielokrotno kta): public Angle mult(double a) { return new Angle(a*this.x); }
284
Programowanie w jzyku Java public Angle mult(int n) { return new Angle(n*this.x); }
Dzielenie miary kta (obiektu) przez liczb: public Angle div(double a) { if (a == 0.0) throw new ArithmeticException("Dzielenie przez 0!"); return new Angle(a*this.x/a); } public Angle div(int n) { if (n == 0) throw new ArithmeticException("Dzielenie przez 0!"); return new Angle(this.x/n); }
Przykad dziaania metod mult() i div(): /** Zadanie Z21.12 */ public class Z21 12 { /* Tu wstaw kod metody: writeln */ public static void main(String args[]) { Angle a = new Angle("22°30'"); writeln("a", a); writeln("2a", a.mult(2)); writeln("4a", a.mult(4)); writeln("1.5a", a.mult(1.5)); writeln("a/2", a.div(2)); } }
Wyniki bd wywietlanie w postaci 1.5a = 0.5890486225480862 rad = 33.75°. Jeli chcemy, aby miara stopniowa bya podawana z minutami i sekundami, to naley w kodzie metody writeln() zamieni wiersz: w.append(" = ").append(x.degree()).append("\u00B0");
na nastpujcy: w.append(" = ").append(x.toString());
Zadanie 21.13. Z21 13.java, Angle.java W metodach statycznych prod() i quot() sucych do dzielenia obiektów Angle (miar któw) przez liczb wywoamy metody mult() i div() (pokazane w rozwizaniu zadania 21.12) dla obiektu podanego jako pierwszy parametr. Drugi parametr (liczb) przekaemy jako parametr do metod mult() i div(). public static Angle prod(Angle x, double y) { return x.mult(y); } public static Angle prod(Angle x, int n) { return x.mult(n); } public static Angle quot(Angle x, double y) { return x.div(y);
Rozdzia 7. i Rozwizania zada
285
} public static Angle quot(Angle x, int n) { return x.div(n); }
Przykad dziaania metod statycznych prod() i quot(): /** Zadanie Z21.13 */ public class Z21 13 { /* Tu wstaw kod metody: writeln */ public static void main(String args[]) { Angle a = new Angle("11°15'"); writeln("a", a); writeln("2a", Angle.prod(a, 2)); writeln("4a", Angle.prod(a, 4)); writeln("1.5a", Angle.prod(a, 1.5)); writeln("a/3", Angle.quot(a, 2)); } }
Zadanie 21.14. Z21 14.java, Angle.java Definiujemy publiczne i statyczne stae typu obiektowego i nadajemy im odpowiednie wartoci. Ze wzgldu na uycie sowa final nie bdziemy mogli tym staym przypisa referencji do innych obiektów, np. Angle RADIAN = new Angle(2.0). Niestety, moliwo zmiany pola obiektu przy uyciu metod setOfXxx (zob. zadania 21.6 i 21.7) jest nadal aktualna. public public public public public public public
static static static static static static static
final final final final final final final
Angle Angle Angle Angle Angle Angle Angle
RIGHT ANGLE = new Angle(Math.PI/2); STRAIGHT ANGLE = new Angle(Math.PI); FULL ANGLE = new Angle(2*Math.PI); RADIAN = new Angle(1.0); DEGREE = new Angle(1); ARCMINUTE = new Angle(0, 1); ARCSECOND = new Angle(0, 0, 1);
W przykadzie wywietlimy wartoci miar któw reprezentowanych przez zdefiniowane stae. /** Zadanie Z21.14 */ public class Z21 14 { public static void main(String args[]) { System.out.println("Kt prosty: "+Angle.RIGHT ANGLE); System.out.println("Kt pópeny: "+Angle.STRAIGHT ANGLE); System.out.println("Kt peny: "+Angle.FULL ANGLE); System.out.println("1 radian: "+Angle.RADIAN); System.out.println("PI radian: "+Angle.RADIAN.mult(Math.PI)); System.out.println("1 stopie : "+Angle.DEGREE); System.out.println("1 minuta ktowa: "+Angle.ARCMINUTE); System.out.println("1 sekunda ktowa: "+Angle.ARCSECOND); } }
Zwrómy uwag na moliwo wykonywania oblicze (przy uyciu metod) zwizanych z tymi staymi, np. Angle.RADIAN.mult(Math.PI).
286
Programowanie w jzyku Java
Zadanie 21.15. Z21 15.java, Angle.java Kty dopeniajce maj wspólne jedno rami i ich suma jest ktem prostym (co moemy wyrazi wzorem D E 90q , czyli E 90q D ). public static Angle compl(Angle x) { if (x.x < 0.0 && x.x > RIGHT ANGLE.x) throw new IllegalArgumentException(); return RIGHT ANGLE.sub(x); }
Kty przylege maj wspólne jedno rami i ich suma jest ktem pópenym ( D E czyli E 180q D ).
180q ,
public static Angle suppl(Angle x) { if (x.x < 0.0 && x.x > STRAIGHT ANGLE.x) throw new IllegalArgumentException(); return STRAIGHT ANGLE.sub(x); }
Przykad oblicze z zastosowaniem metod compl() i suppl(): /** Zadanie Z21.15 */ public class Z21 15 { public static void main(String args[]) { Angle alfa = new Angle(27, 32, 15); System.out.println("alfa = "+alfa); System.out.println("Kt dopeniajcy do alfa: "+ Angle.compl(alfa)); System.out.println("Kt przylegy do alfa: "+Angle.suppl(alfa)); } }
Zadanie 21.16. Z21 16.java Do wczytywania danych wykorzystamy obiekt input klasy Scanner. Najpierw sprawdzimy, czy w strumieniu danych jest liczba cakowita. Jeli tak, to potraktujemy j jako miar kta wyraon w stopniach. W przeciwnym razie sprawdzamy, czy nie jest to liczba zmiennoprzecinkowa. Jeli wprowadzono liczb zmiennoprzecinkow, to zamieniamy t liczb (traktowan jako miar kta w stopniach) na radiany i wywoujemy odpowiedni metod. Natomiast gdy w strumieniu nie ma liczby, to spodziewamy si tekstu o postaci 23°35'25". Bdny cig znaków wygeneruje wyjtek zgoszony przez konstruktor Angle(String). private static Angle inputAngle(String s) { System.out.print("Podaj "+s); Scanner input = new Scanner(System.in); if (input.hasNextInt()) return new Angle(input.nextInt()); else if (input.hasNextDouble()) return new Angle(Math.toRadians(input.nextDouble())); else { String str = input.next(); return new Angle(str); } }
Rozdzia 7. i Rozwizania zada
287
W trójkcie równoramiennym kty przy podstawie ( E ) maj równe miary. Suma któw wewntrznych trójkta jest ktem pópenym: D 2E 180q , czyli 2E 180q D 180q D (do oblicze wykorzystamy metod suppl()). Std E , co moemy wyrazi 2
formu Angle beta = Angle.suppl(alfa).div(2). Sprawdzenie oblicze wykonamy, dodajc miary wszystkich któw trójkta: beta.mult(2).add(alfa). import java.util.Scanner; /** Zadanie Z21.16 */ public class Z21 16 { /* Tu wstaw kod metody inputAngle. */ public static void main(String args[]) { System.out.println("Obliczanie miar któw w trójkcie równoramiennym."); Angle alfa = inputAngle("Kt przy wierzchoku trójkta równoramiennego,\nalfa = "); Angle beta = Angle.suppl(alfa).div(2); System.out.println("Kt przy wierzchoku trójkta równoramiennego, alfa = "+alfa); System.out.println("Kt przy podstawie trójkta równoramiennego, beta = "+beta); System.out.println("Sprawdzenie suma któw w trójkcie:"+ beta.mult(2).add(alfa)); } }
Zadanie 21.17. Z21 17.java Do wprowadzania danych wykorzystamy metod inputAngle() omówion w rozwizaniu zadania 21.16. Kt lecy naprzeciw podstawy w trójkcie równoramiennym obliczymy ze wzoru D 180q 2E , gdzie E jest miar kta przylegego do podstawy. Obliczenie to zrealizujemy w nastpujcy sposób: Angle alfa = Angle.suppl(beta. mult(2)). import java.util.Scanner; /** Zadanie Z21.17 */ public class Z21 17 { /* Tu wstaw kod metody inputAngle. */ public static void main(String args[]) { System.out.println("Obliczanie miar któw w trójkcie równoramiennym."); Angle beta = inputAngle("Kt przy podstawie trójkta równoramiennego,\nalfa = "); Angle alfa = Angle.suppl(beta.mult(2)); System.out.println("Kt przy podstawie trójkta równoramiennego, beta = "+beta); System.out.println("Kt przy wierzchoku trójkta równoramiennego, alfa = "+alfa); System.out.println("Sprawdzenie suma któw w trójkcie: "+beta.mult(2).add(alfa)); } }
Obliczenia sprawdzimy, dodajc miary któw trójkta: beta.mult(2).add(alfa).
288
Programowanie w jzyku Java
Zadanie 21.18. Z21 18.java Do wprowadzania danych (dugoci odcinków) wykorzystamy metod inputSide() (ang. side — bok wielokta). private static Double inputSide(String s) { System.out.print("Podaj "+s); Scanner input = new Scanner(System.in); return input.nextDouble(); }
Do wyznaczenia miary kta moemy zastosowa twierdzenie cosinusów (bdce uogólnieniem twierdzenia Pitagorasa), wyraone wzorem c 2 a 2 b 2 2ab cos J (kt J a2 b2 c2 . Przestawiajc cyklicznie 2ab
ley naprzeciw boku c). Std obliczymy cos J
dugoci boków, otrzymamy kolejne wzory: cos D (po uporzdkowaniu cos E
b2 b2 a 2 2bb
c2 a2 b2 2ca
a2 c2 b2 ). 2ac
Podstawiajc b = c we wzorze cos D cosD
b2 c2 a2 i cos E 2bc
2b 2 a 2 2b 2
1
b2 c2 a2 , otrzymamy 2bc a2 2b 2
Na podstawie tego wzoru obliczymy: alfa.setOfCos(1 a*a/(2*b*b));
Kt E moemy obliczy w sposób poznany w rozwizaniu zadania 21.16: Angle beta = Angle.suppl(alfa).div(2)
lub ponownie stosujc wzór wynikajcy z twierdzenia cosinusów: cos E
c2 a2 b2 2ca
b2 a 2 b2 2ba
a2 2ab
a 2b
beta.setOfCos(a/2/b);
Kod programu przedstawia si nastpujco: import java.util.Scanner; /** Zadanie Z21.18 */ public class Z21 18 { /* Tu wstaw kod metody inputSide. */ public static void main(String args[]) { System.out.println("Obliczanie miar któw w trójkcie równoramiennym."); double a = inputSide("Dugo podstawy trójkta równoramiennego,\na = "); double b = inputSide("Dugo ramienia trójkta równoramiennego,\nb = ");
Rozdzia 7. i Rozwizania zada
289
Angle alfa = new Angle(0); alfa.setOfCos(1 a*a/(2*b*b)); Angle beta = new Angle(0); beta.setOfCos(a/2/b); System.out.println("Kt przy wierzchoku trójkta równoramiennego, alfa = "+alfa); System.out.println("Kt przy podstawie trójkta równoramiennego, beta = "+beta); System.out.println("Sprawdzenie suma któw w trójkcie: "+ beta.mult(2).add(alfa)); } }
Zadanie 21.19. Z21 19.java Do wprowadzania danych (dugoci odcinków) wykorzystamy metod inputSide() przedstawion w rozwizaniu zadania 21.18. Wysoko opuszczona na podstaw dzieli trójkt równoramienny na dwa przystajce trójkty prostoktne o przyprostoktnych o dugoci a i h (kty ostre lece naprze2
ciw tych boków maj miary D i E ). Poniewa tan D miar kta D :
2
2
a 2 h
a , to moemy obliczy 2h
alfa.setOfTan(a/2/h); // poowa kta alfa alfa = alfa.mult(2); // kt alfa
Podobnie obliczymy tan E
h a 2
2h , wic: a
beta.setOfTan(2*h/a); // kt beta
Oto kompletny kod programu: import java.util.Scanner; /** Zadanie Z21.19 */ public class Z21 19 { /* Tu wstaw kod metody inputSide. */ public static void main(String args[]) { System.out.println("Obliczanie miar któw w trójkcie równoramiennym."); double a = inputSide("Dugo podstawy trójkta równoramiennego,\na = "); double h = inputSide("Wysoko trójkta równoramiennego,\nh = "); Angle beta = new Angle(0); beta.setOfTan(2*h/a); Angle alfa = new Angle(0); alfa.setOfTan(a/2/h); alfa = alfa.mult(2); System.out.println("Kt przy wierzchoku trójkta równoramiennego, alfa = "+alfa); System.out.println("Kt przy podstawie trójkta równoramiennego, beta = "+beta);
290
Programowanie w jzyku Java System.out.println("Sprawdzenie beta.mult(2).add(alfa));
suma któw w trójkcie: "+
} }
Zadanie 21.20. Z21 20.java Do wprowadzania danych (dugoci boków trójkta) zastosujemy metod inputSide() przedstawion w rozwizaniu zadania 21.18. Miary któw obliczymy na podstawie twierdzenia cosinusów — wzory omówiono w rozwizaniu zadania 21.18. import java.util.Scanner; /** Zadanie Z21.20 */ public class Z21 20 { /* Tu wstaw kod metody inputSide. */ public static void main(String args[]) { System.out.println("Obliczanie miar któw w trójkcie o bokach a, b i c."); double a = inputSide("Dugo boku trójkta,\na = "); double b = inputSide("Dugo boku trójkta,\nb = "); double c = inputSide("Dugo boku trójkta,\nc = "); Angle alfa = new Angle(0); alfa.setOfCos((b*b+c*c a*a)/(2*b*c)); Angle beta = new Angle(0); beta.setOfCos((a*a+c*c b*b)/(2*a*c)); Angle gamma = new Angle(0); gamma.setOfCos((a*a+b*b c*c)/(2*a*b)); System.out.println("alfa = "+alfa); System.out.println("beta = "+beta); System.out.println("gamma = "+gamma); System.out.println("Sprawdzenie suma któw w trójkcie: "+ alfa.add(beta).add(gamma)); } }
Po obliczeniu miar dwóch któw ( D i E ) miar trzeciego kta moemy wyznaczy ze wzoru J
180q D E :
Angle gamma = Angle.diff(Angle.STRAIGHT ANGLE, Angle.sum(alfa, beta));
lub: Angle gamma = Angle.STRAIGHT ANGLE.sub(alfa.add(beta));
22. Liczby rzymskie i klasa Roman Zadanie 22.1. Z22 1.java Analizujc zapis liczb rzymskich (z zakresu od 1 do 3999), moemy zauway, e symbole M (1000), C (100), X (10) i I (1) mog powtarza si do trzech razy obok siebie, a symbole D (500), L (50) i V (5) wystpuj maksymalnie jeden raz. Ponadto wane s kombinacje dwóch znaków: CM (900), CD (400), XC (90), XL (40), IX (9) i IV (4).
Rozdzia 7. i Rozwizania zada
291
Kod zamieniajcy liczb n na cig znaków w systemie rzymskim jest obszerny, ale niezbyt trudny do zrozumienia. Liczb n zmniejszamy kolejno, jeli jest to moliwe, o wartoci 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1. W zamian za to do wyniku dodajemy odpowiednio znaki M, CM, D, CD, C, XC, L, XL, X, IX, V, IV, I. Znaki M, C, X i I mog wystpi co najwyej trzykrotnie (std uycie ptli while), pozostae tylko raz. Naley zauway, e wystpienie CM wyklucza pojawienie si D, CD i C w dalszej czci cigu znaków, podobnie D wyklucza CD i C oraz CD wyklucza C (stosujemy zagniedone instrukcje warunkowe). Podobne reguy obowizuj dla zestawu znaków XC, L, XL i X oraz IX, V, IV i I. StringBuilder tmp = new StringBuilder(""); /* Znaki rzymskie M, CM, D i CD - liczby 1000, 900, 500, 400 */ while (n >= 1000) { n = 1000; tmp.append("M"); } if (n >= 900) { n = 900; tmp.append("CM"); } else if (n >= 500) { n = 500; tmp.append("D"); } else if (n >= 400) { n = 400; tmp.append("CD"); } /* Znaki rzymskie C, XC, L, XL - liczby 100, 90, 50, 40 */ while (n >= 100) { n = 100; tmp.append("C"); } if (n >= 90) { n = 90; tmp.append("XC"); } else if (n >= 50) { n = 50; tmp.append("L"); } else if (n >= 40) { n = 40; tmp.append("XL"); } /* Znaki rzymskie X, IX, V, IV - liczby 10, 9, 5, 4 */ while (n >= 10) { n = 10; tmp.append("X"); } if (n >= 9) { n = 9; tmp.append("IX"); } else if (n >= 5) { n = 5; tmp.append("V"); } else if (n >= 4) { n = 4;
292
Programowanie w jzyku Java tmp.append("IV"); } /* Znak I - liczba 1 */ while (n >= 1) { n = 1; tmp.append("I"); }
Obiekt tmp zawiera pocztkow warto liczby n w zapisie rzymskim (aktualna warto n jest zerem). Pobieran z klawiatury warto liczby bdziemy przechowywali w zmiennej liczba (typu int). W programie utworzymy ptl ze sprawdzaniem warunku na kocu — dziaanie ptli przerwiemy, gdy zmienna liczba bdzie miaa warto 0. W ptli wczytujemy liczb cakowit i sprawdzamy, czy jej warto mieci si w zakresie od 1 do 3999. Jeli liczba jest poza tym zakresem, wywietlamy stosowny komunikat ("Liczba poza zakresem.") i przechodzimy (instrukcj continue) do sprawdzania warunku powtarzania ptli, pomijajc kod zamiany n na liczb w systemie rzymskim. import java.util.Scanner; /** Zadanie Z22.1 */ public class Z22 1 { public static void main(String args[]) { Scanner input = new Scanner(System.in); System.out.println("Rzymski sposób zapisu liczb od 1 do 3999"); int liczba; do { System.out.print("Podaj liczb (0 koniec oblicze ), n = "); liczba = input.nextInt(); if (liczba < 1 || liczba > 3999) { System.out.println("Liczba poza zakresem."); continue; } int n = liczba; /* Tu wstaw kod zamiany n na liczb w systemie rzymskim */ System.out.println(liczba+" = "+tmp.toString()); } while (liczba !=0); } }
Stosujc dwie tablice z wartociami wybranych liczb rzymskich i odpowiadajcych im wartoci dziesitnych: private static final String[] rz = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; private static final int[] ar = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
moemy uproci kodowanie liczb w systemie rzymskim. StringBuilder tmp = new StringBuilder(""); for(int i = 0; i= ar[i]) {
Rozdzia 7. i Rozwizania zada
293
n = ar[i]; tmp.append(rz[i]); } }
Na pocztku warto zmiennej n jest równa konwertowanej liczbie i mieci si w zakresie od 1 do 3999. Elementy w obu tablicach s uporzdkowane od wartoci najwikszej (1000) do najmniejszej (1). Bierzemy kolejne wartoci i dopóki liczba jest wiksza od tej wartoci, dopóty do cigu znaków rzymskich dodajemy odpowiedni symbol, a liczb zmniejszamy o t warto. Po dojciu do koca tablicy mamy poprawnie zakodowan liczb w systemie rzymskim.
Zadanie 22.2. Z22 2.java Oprócz tablic (wprowadzonych w rozwizaniu zadania 22.1): private static final String[] rz = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; private static final int[] ar = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
dodamy tablic lp zawierajc maksymaln liczb powtórze symboli z tablicy rz: private static final int[] lp = {3, 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3};
oraz tablic err z niedozwolonymi kombinacjami symboli: private static final String[] err = {"CMD", "CMC", "XCL", "XCX", "IXV", "IXI", "DCD", "CDC", "LXL", "XLX", "VIV", "IVI"};
Cig symboli CMD oznaczaby liczb 900+500 = 1400, któr poprawnie zapisujemy w postaci MCD (1000+400). Kolejny cig CMC mona interpretowa jako 900+100 = 1000, ale to nie ma sensu, bo 1000 zapisujemy jednym znakiem M. Podobnie jest z pozostaymi cigami uznanymi za bdne i zapisanymi w tablicy err. Najpierw sprawdzimy, czy podany cig znaków (roman) nie zawiera niedozwolonych cigów zapisanych w tablicy err. Przegldajc tablic bdnych sekwencji znaków, sprawdzamy, czy wystpuj w acuchu roman. Jeli tak si zdarzy, to metoda indexOf() zwróci warto -1 i zostanie zgoszony wyjtek. for (String x: err) if (roman.indexOf(x) != 1) throw new ArithmeticException("Niewaciwy cig znaków: "+x+ " w "+roman);
Jeli cig wejciowy nie zawiera niedozwolonych sekwencji, moemy ustali pocztkow warto wyniku (tmp) i zainicjowa indeks analizowanego znaku rzymskiego (pobieranego z tablicy rz). int tmp = 0; int index = 0;
// indeks analizowanego znaku rzymskiego
Przegldamy w ptli (for (int i = 0; i < 13; i++)) tablic rz.
294
Programowanie w jzyku Java
Zerujemy (int powt = 0) licznik powtórze symbolu rz[i]. W ptli (while) sprawdzamy, ile razy symbol rzymski (rz[i]) pojawia si w cigu znaków roman. Kada pozytywna odpowied powoduje zwikszenie zmiennej tmp (tmp += ar[i]) o warto (ar[i]) odpowiadajc sprawdzanemu symbolowi (rz[i]), zwikszenie indeksu o rozmiar symbolu (index += rz[i].length()) i zwikszenie licznika powtórze (++powt). Badany na pocztku ptli while warunek roman.startsWith(rz[i], index) sprawdza, czy w acuchu roman na pozycji o indeksie index rozpoczyna si cig znaków rz[i] — wynik jest wartoci logiczn (true lub false). Po wyjciu z ptli while sprawdzamy, czy symbol rz[i] nie wystpi zbyt wiele razy (if (powt > lp[i])...). Jeli liczba powtórze przekracza dozwolon liczb (zapisan w tabeli lp), to zgaszany jest wyjtek. Po wyjciu z ptli for dokonujemy jeszcze jednego sprawdzenia: if (index != roman.length()) throw new ArithmeticException("Niewaciwa liczba rzymska: "+roman);
Rozbieno pomidzy wartoci zmiennej index i dugoci acucha roman wiadczy o niepoprawnej budowie liczby rzymskiej. Poniszy kod zamienia acuch znaków roman na liczb tmp lub zgasza wyjtek: for (String x: err) if (roman.indexOf(x) != 1) throw new ArithmeticException("Niewaciwy cig znaków: "+ x+" w "+roman); int tmp = 0; // warto pocztkowa wyniku int index = 0; // indeks analizowanego znaku for (int i = 0; i < 13; i++) { int powt = 0; while (roman.startsWith(rz[i], index)) { tmp += ar[i]; index += rz[i].length(); ++powt; } if (powt > lp[i]) throw new ArithmeticException("Za duo znaków: "+rz[i]+" w "+roman); } if (index != roman.length()) throw new ArithmeticException("Niewaciwa liczba rzymska: "+roman);
W gównej ptli programu (do {...} while(true);) wczytujemy liczb rzymsk, dokonujemy jej zamiany na liczb dziesitn i wywietlamy wynik. Ptla zostanie przerwana (wiadomie przez uytkownika) po wprowadzeniu pustego acucha znaków lub w wyniku bdnej postaci liczby (wystpi wyjtek). Ewentualne przechwycenie i obsuenie wyjtku pozostawimy Czytelnikowi. import java.util.Scanner; /** Zadanie Z22.2 */ public class Z22 2 { /* Tu wstaw cztery tablice: rz, ar, lp i err. */ public static void main(String args[]) { Scanner input = new Scanner(System.in);
Rozdzia 7. i Rozwizania zada
295
System.out.println("Odczytywanie liczb rzymskich"); String roman; do { System.out.print("Podaj liczb rzymsk: "); roman = input.next(); if (roman.equals("")) break; /* Tu wstaw kod zamiany liczb rzymskich na dziesitne. */ System.out.println(roman+" = "+tmp); } while (true); } }
Zadanie 22.3. Z22 3.java Na podstawie rozwizania zadania 22.1 moemy zbudowa nastpujc metod: private static String decToRoman(int n) { if (n < 1 || n > 3999) throw new ArithmeticException("Liczba poza zakresem: "+n); String[] rz = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; int[] ar = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; StringBuilder tmp = new StringBuilder(""); for(int i = 0; i= ar[i]) { n = ar[i]; tmp.append(rz[i]); } } return tmp.toString(); }
Tablice niezbdne do konwersji liczb dziesitnych na rzymskie zostay umieszczone w kodzie metody. Zatem kod metody jest kompletny i moe w tej postaci by przenoszony do dowolnej aplikacji. Dziaanie metody pokaemy dla kilkunastu liczb wybranych w sposób losowy. /** Zadanie Z22.3 */ public class Z22 3 { /* Tu wstaw kod metody decToRoman() */ public static void main(String args[]) { System.out.println("Zapis liczb w systemie rzymskim"); for(int i = 0; i < 15; ++i) { int n = (int)(1+3999*Math.random()); System.out.println(n+" = "+decToRoman(n)); } } }
Definicje tablic rz i ar moemy umieci w kodzie klasy (tak jak w zadaniu 21.1 lub 21.2) i usun z kodu metody decToRoman().
296
Programowanie w jzyku Java
Zadanie 22.4. Z22 4.java Utworzymy klas RN z dwoma polami: r typu String (do przechowywania symboli rzymskich) oraz d typu int (do przechowywania wartoci dziesitnej symbolu). Klas definiujemy z modyfikatorem final — po tej klasie nie bdzie mona dziedziczy. Pola klasy definiujemy z modyfikatorami protected i final (do pól bdzie dostp, ale po utworzeniu obiektu nie bdzie mona zmieni wartoci pól). Konstruktor deklarujemy jako metod prywatn. Poza klas RN konstruktor nie bdzie dostpny. Wykorzystamy go tylko do utworzenia trzynastoelementowej tablicy rn (statycznej i finalnej), czyli jedynego elementu udostpnionego przez zdefiniowan klas. final class RN { protected final String r; protected final int d; private RN(String r, int d) { this.r = r; this.d = d; }; static final RN[] rn = {new RN("M", 1000), new RN("CM", 900), new RN("D", 500), new RN("CD", 400), new RN("C", 100), new RN("XC", 90), new RN("L", 50), new RN("XL", 40), new RN("X", 10), new RN("IX", 9), new RN("V", 5), new RN("IV", 4), new RN("I", 1)}; }
Z tej tablicy moe korzysta metoda decToRoman(): private static String decToRoman(int n) { StringBuilder tmp = new StringBuilder(""); for(int i = 0; i= RN.rn[i].d) { n = RN.rn[i].d; tmp.append(RN.rn[i].r); } } return tmp.toString(); }
Pokazujc dziaanie metody, wywietlimy potgi liczby 2 zapisane w systemie rzymskim. /** Zadanie Z22.4 */ /* Tu wstaw kod klasy RN.*/ public class Z22 4 { /* Tu wstaw kod metody decToRoman(). */ public static void main(String args[]) { System.out.println("Potgi liczby 2 w systemie rzymskim"); int i = 0, n = 1; while (i < 13) { System.out.println("2^"+i+" = "+decToRoman(n)); ++i; n *= 2; } } }
Rozdzia 7. i Rozwizania zada
297
Kody obu klas (RN i Z22 4) znajdoway si w jednym pliku: Z22 4.java. Po kompilacji otrzymujemy dwa pliki: RN.class i Z22 4.class — kada skompilowana klasa znajduje si w odrbnym pliku.
Zadanie 22.5. Z22 5.java Wykorzystajmy klas RN i metod decToRoman() z rozwizania zadania 22.4. Na podstawie rozwizania zadania 22.2 moemy zbudowa metod: private int int for
static int romanToDec(String s) { tmp = 0; index = 0; // indeks analizowanego znaku (int i = 0; i < 13; i++) while (s.startsWith(RS.rn[i].r, index)) { tmp += RS.rn[i].d; index += RS.rn[i].r.length(); } if (!s.equals(decToRoman(tmp)) || tmp > 3999) throw new ArithmeticException("Niewaciwa liczba rzymska: "+s); return tmp;
}
Dziaanie metody sprawdzimy dla kilku liczb rzymskich zapisanych w tablicy. /** Zadanie Z22.5 */ /* Tu wstaw kod klasy RN lub w biecym folderze umie skompilowany plik klasy (RN.class). */ public class Z22 5 { /* Tu wstaw kod metody decToRoman(). */ /* Tu wstaw kod metody romanToDec(). */ public static void main(String args[]) { System.out.println("Odczytywanie liczb w systemie rzymskim"); String[] test = {"XXVII", "CCXLV", "III", "MMMCMXCIX", "MXXIV"}; for(String r: test) System.out.println(r+" = "+romanToDec(r)); } }
Zadanie 22.6. Z22 6.java, Roman.java Na pocztek tworzymy klas z jednym prywatnym polem (int n;) i publicznym konstruktorem z jednym parametrem — liczb cakowit. Jeli podana liczba nie mieci si w zakresie od 1 do 3999, to wygenerowany zostanie wyjtek. public class Roman { private int n; public Roman(int n) { if(n < 1 || n > 3999) throw new ArithmeticException("Liczba poza zakresem");
298
Programowanie w jzyku Java else this.n = n; } }
Klas moemy rozszerzy o kolejne metody — metod zwracajc warto dziesitn liczby naturalnej przechowywanej w obiekcie: public int intValue() { return n; }
oraz metod statyczn zwracajc obiekt klasy Roman odpowiadajcy podanej liczbie cakowitej: public static Roman valueOf(int n) { return new Roman(n); }
Z klasy w tej postaci jest jeszcze niewielki poytek. Do jej kodu dodamy wewntrzn klas RN (z rozwizania zadania 22.4), dopisujc w nagówku modyfikator static: private static final class RN { final String r; final int d; private RN(String r, int d) { this.r = r; this.d = d; }; static final RN[] rn = {new RN("M", 1000), new RN("CM", 900), new RN("D", 500), new RN("CD", 400), new RN("C", 100), new RN("XC", 90), new RN("L", 50), new RN("XL", 40), new RN("X", 10), new RN("IX", 9), new RN("V", 5), new RN("IV", 4), new RN("I", 1)}; }
oraz metody statyczne korzystajce z tablicy rn zdefiniowanej w tej klasie (tym razem zadeklarowane jako publiczne): decToRoman() (zadanie 22.4) i romanToDec() (zadanie 22.5). public static String decToRoman(int n) { StringBuilder tmp = new StringBuilder(""); for(int i = 0; i= RN.rn[i].d) { n = RN.rn[i].d; tmp.append(RN.rn[i].r); } } return tmp.toString(); } public static int romanToDec(String s) { int tmp = 0; int index = 0; // indeks analizowanego znaku for (int i = 0; i < 13; i++) while (s.startsWith(RN.rn[i].r, index)) { tmp += RN.rn[i].d;
Rozdzia 7. i Rozwizania zada
299
index += RN.rn[i].r.length(); } if (!s.equals(decToRoman(tmp)) || tmp > 3999) throw new ArithmeticException("Niewaciwa liczba rzymska: " +s); return tmp; }
Korzystajc z metody decToRoman(), moemy przesoni metod toString() dziedziczon z klasy Object: @Override public String toString() { return decToRoman(this.n); }
Natomiast metod romanToDec() moemy zastosowa do zbudowania konstruktora tworzcego nowy obiekt na podstawie liczby zapisanej w systemie rzymskim lub statycznej metody nadajcej obiektowi now warto utworzon na podstawie acucha znaków. public Roman(String s) { this.n = romanToDec(s);; } public static Roman valueOf(String s) { return new Roman(s); }
Teraz moemy uzna klas Roman za kompletn. Klasa RN jest klas wewntrzn klasy Roman i jej kod ródowy znajduje si w pliku Roman.java. Po kompilacji otrzymujemy dwa pliki: Roman.class i Roman$RN.class — kada skompilowana klasa znajduje si w odrbnym pliku. Klasa RN jest dostpna jednak wycznie wewntrz klasy Roman.
Przykad wykorzystania obiektów i metod klasy Roman: /** Zadanie Z22.6 */ public class Z22 6 { public static void main(String args[]) { Roman a = new Roman(2012); System.out.println(a.intValue()+" = "+a); Roman b = Roman.valueOf("XLIV"); System.out.println(b.intValue()+" = "+b); a = Roman.valueOf(137); System.out.println(a.intValue()+" = "+a); Roman c = new Roman("MMMCMXCIX"); System.out.println(c.intValue()+" = "+c); System.out.println("175 = "+Roman.decToRoman(175)); System.out.println("XXXIV = "+Roman.romanToDec("XXXIV")); System.out.println("MMMM = "+Roman.romanToDec("MMMM")); } }
300
Programowanie w jzyku Java
Zadanie 22.7. Z22 7.java Ustalimy liczb pyta (int pytania = 10) i maksymaln warto wylosowanej liczby (int zakres = 50). Na podstawie tych parametrów utworzymy tablic a, wypenion wylosowanymi i niepowtarzajcymi si wartociami. W tym celu wykorzystamy metod rndUniqueArray() z klasy MyRandomArray. Wystarczy, e do biecego folderu skopiujemy skompilowany kod klasy (MyRandomArray.class) lub kod ródowy klasy (MyRandomArray.java). Nastpnie wartoci elementów tablicy zwikszymy o 1; w ten sposób otrzymamy liczby z zakresu od 1 do 50 (zmienna zakres). Ustalimy liczb punktów (int pkt = 0). W ptli zamieniamy liczb z tablicy na obiekt klasy Roman. Wypisujemy liczb rzymsk w konsoli. Uytkownik podaje warto dziesitn tej liczby. Jeli podana warto jest równa liczbie rzymskiej ( n == roman.int Value()), powikszamy liczb punktów (++pkt). Po zakoczeniu ptli wywietlimy wynik — sum zdobytych punktów. import java.util.Scanner; /** Zadanie Z22.7 */ public class Z22 7 { public static void main(String args[]) { Scanner input = new Scanner(System.in); int pytania = 10; // 10 pyta int zakres = 50; // najwiksza liczba 50 int[] a = MyRandomArray.rndUniqueArray(pytania, zakres); MyRandomArray.addToArray(a, 1); int pkt = 0; Roman roman; for(int i = 0; i < pytania; ++i) { roman = Roman.valueOf(a[i]); System.out.print(roman+" = "); int n = input.nextInt(); if (n == roman.intValue()) ++pkt; } System.out.println("Wynik: "+pkt+" z "+pytania+"."); } }
Zadanie 22.8. Z22 8.java Rozwizanie jest podobne do rozwizania zadania 22.7. Rónica polega na odwróceniu czynnoci w gównej ptli programu. Wywietlamy warto dziesitn liczby, a uytkownik wprowadza rzymsk posta tej liczby. Do porównania acuchów znaków — wprowadzonego przez uytkownika (s) i przedstawiajcego liczb rzymsk (roman.toString()) — uyjemy metody equals() z klasy String. int pkt = 0; Roman roman; for(int i = 0; i < pytania; ++i) { roman = Roman.valueOf(a[i]); System.out.print(a[i]+" = "); String s = input.next(); if (s.equals(roman.toString())) ++pkt; } System.out.println("Wynik: "+pkt+" z 10.");