Po co nam zmienne? Czyli przeprowadzamy operacje na liczbach.

“Zmienne” są bardzo ważnym narzędziem w rękach programisty. Z poprzedniego posta Zmienne w języku Java wiemy już, że dzięki nim możemy przechowywać w pamięci różne ważne dla nas rzeczy, aby wykorzystać je później. Ale do czego wykorzystać? W dzisiejszym poście poznamy bardziej praktyczne zastosowania zmiennych i zobaczymy jakie operacje możemy na nich wykonywać.

Jednym z takich zastosowań jest szeroko pojęta matematyka. Otóż dwie zmienne możemy do siebie np. dodać, odjąć czy je pomnożyć. Jeżeli zmienna jest typu liczbowego (czyli byte, short, int, long, float, double) to stosują się do nich standardowe operacje matematyczne znane ze szkoły.

Operacje matematyczne na zmiennych liczbowych w języku Java:

  • dodawanie: +
  • odejmowanie: –
  • mnożenie: *
  • dzielenie: /
  • dzielenie z resztą: %

Przyjrzyjmy się przykładowi. Mamy dwie zmienne: “liczbaA” oraz “liczbaB”. W linijkach 6 i 7 ustawiamy ich wartości na “7” i “14”. Przypomnę, że możemy sobie to wyobrazić jako włożenie do dwóch oddzielnych przegródek dwóch liczb: “7” i “14”. Będą one do dyspozycji za chwilę. W linijkach 9 – 13 tworzymy nowe zmienne: “suma”, “roznica”, “iloczyn”, “iloraz” oraz “reszta”. Od razu przypisujemy im wartości odpowiednie dla każdej ze wspomnianych matematycznych operacji.

Na koniec tego programu wypisujemy na ekran wartości poszczególnych zmiennych.

p1

Hmm czy w końcowych wynikach widzisz może coś dziwnego? Dlaczego wynik dzielenia “7” przez “14” to “0”? Przecież jeśli podzielimy te dwie liczby to dostaniemy “0,5”. Na powyższym przykładzie widzimy, jak ważne w programie jest dobranie odpowiedniego typu zmiennej. Otóż wszystkie nasze zmienne mają typ int (czyli Integer: liczba całkowita). I podczas działania program zmienia wynik dzielenia na część całkowitą i niejako odcina część ułamkową.

Dlatego też, jeśli przewidujemy, że wynikiem operacji może być liczba ułamkowa, to należy zastosować inny typ zmiennej. Do przechowywania ułamków służą typy zmiennoprzecinkowe, czyli float oraz double.

Zamieńmy teraz wszystkie typy z int na float. Po uruchomieniu programu wyniki są już poprawne.

p2

Zachęcam do samodzielnego sprawdzenia różnych typów danych i kombinacji na stronie JDoodle lub IDE.

Nasuwa się teraz pytanie, dlaczego zawsze nie stosować typów zmiennoprzecinkowych? Przecież można za każdym razem używać tego najbardziej dokładnego typu. Otóż w tym przypadku poświęcamy dokładność kosztem rozmiaru. Każda zmienna w pamięci zajmuje określony rozmiar. Jeśli wrócimy do naszego porównania zmiennych do przegródek, to typ zmiennej określa to co możemy w danej przegródce trzymać oraz jej rozmiar. To tak jakby nasze przegródki były różnej wielkości.

Do tych małych możemy włożyć małe liczby. Na większe liczby potrzebujemy odpowiednio więcej miejsca. I nie chodzi tutaj też o to, że liczba “0,5” jest mała (np. jest mniejsza niż “1”). Typ zmiennoprzecinkowy musi mieć bardzo dużą przegródkę, bo musi mieć miejsce na wszystkie liczby po przecinku, bo może ich być nieskończenie wiele.

Dla przykładu weźmy stałą matematyczną liczbę PI. Większość z nas zna tylko pierwszych kilka cyfr po przecinku (“3,14”), a tak naprawdę jest ich nieskończenie wiele (“3.141592653589793…”). I mimo, że liczba PI będzie zawsze mniejsza od liczby “4”, to w pamięci komputera musi zajmować więcej miejsca, ponieważ chcemy przechowywać wszystkie te liczby po przecinku.

Poniżej wypisałem rozmiary podstawowych typów zmiennych stosowanych w Javie.

  • byte: 1 bajt
  • short: 2 bajty
  • int: 4 bajty
  • long: 8 bajtów
  • float: 4 bajty
  • double: 8 bajtów
  • char: 2 bajty
  • boolean: nie ma dokładnie określonego rozmiaru, ale zawiera “jeden bit informacji”

I co prawda w obecnych czasach mamy do dyspozycji coraz więcej pamięci w komputerach, to jednak jest ona ograniczona i programista musi zwracać uwagę, żeby nie stosować niepotrzebnie zbyt pojemnych typów danych. Należy rozmiary naszych przegródek dostosowywać do wartości jakie będziemy w nich trzymać (o ile jest to możliwe, bo czasami musimy po prostu przyjąć pewien zapas).

Oprócz standardowych operacji matematycznych i ich operatorów (czyli znaków +, -, *, /, %) mamy do dyspozycji tak zwane “operatory unarne”. Standardowe operatory posiadają dwa argumenty, czyli z lewej i prawej strony takiego plusa musi być po jednej “rzeczy”. Operatory unarne mają tylko jeden argument.

Poniżej lista operatorów unarnych w Javie:

  • Przypisanie dodatnie: +=
  • Przypisanie ujemne: -=
  • Inkrementacja (zmiana wartości o 1): ++
  • Dekrementacja (zmiana wartości o 1): —
  • Zaprzeczenie: !

Stosując standardowe operatory matematyczne musielibyśmy napisać trochę więcej kodu żeby osiągnąć to samo co jednym operatorem unarnym. Poniższy program powinien trochę wyjaśnić:

Wykonaj teraz ten program samodzielnie. Wklej go na stronę JDoodle lub w swoim IDE i uruchom a zobaczysz, jak zmieniają się wartości zmiennej w poszczególnych krokach.

Widzimy zamienne zastosowanie poszczególnych operatorów. Zauważ, że operujemy na tej samej zmiennej. Nie jest to przypadkowe, ponieważ operatory unarne zmieniają wartość zmiennej, dla której zostały użyte. Końcowy efekt w tym przypadku jest jednak taki sam. Możemy napisać dodawanie jako “a = a + x” lub “a += x”. Jeżeli “x = 1” to możemy też napisać “a++”, ponieważ operatory inkrementacji i dekrementacji zmieniają wartość zmiennej o 1.

Ciekawostką jest, że operatory inkrementacji i dekrementacji możemy stosować za zmienną i przed zmienną. Oba zapisy są poprawne, jednak ich sens jest troszkę inny. Różnią się kolejnością operacji na zmiennej.

Na poniższym przykładzie możemy to dokładniej prześledzić.

Zastanówmy się przez chwilę, co się dzieje z naszymi przegródkami, jeśli stosujemy operatory matematyczne? Np. dla takiego zapisu: “liczbaDruga = liczbaPierwsza + 1” komputer bierze z przegródki “liczbaPierwsza” wartość, która tam się znajduje, następnie dodaje do niej jeden i wkłada do przegródki “liczbaDruga”.

Przy takim standardowym operatorze, wartość w przegródce “liczbaPierwsza” nie jest zmieniana. Jednak operatory unarne zmieniają wartość zmiennej, na której się wykonują. To jest bardzo ważne. Ważna jest też kolejność tych zmian.

Otóż przy zapisie: “liczbaDruga = liczbaPierwsza++”, program weźmie wartość z przegródki “liczbaPierwsza”, włoży ją do przegródki “liczbaDruga” a na koniec zinkrementuje wartość początkową i włoży ją z powrotem do przegródki “liczbaPierwsza”.

p3

Natomiast w przypadku trzecim, czyli zapisie: “liczbaDruga = ++liczbaPierwsza”, program weźmie wartość z przegródki “liczbaPierwsza”, zinkrementuje jej wartość i włoży tę nową wartość do przegródek “liczbaDruga” oraz “liczbaPierwsza”. Dzieje się tak dlatego, że operator “++” został zapisany przed zmienną, czyli wskazujemy programowi, że w pierwszej kolejności chcemy zwiększyć wartość “liczbaPierwsza”.

Jak widzimy, może to być powodem niejasności, dlatego jeśli nie jesteśmy pewni, lepiej korzystać ze standardowych operatorów matematycznych. Dobrze jest jednak wiedzieć co dokładnie się dzieje w różnych przypadkach, ponieważ czasem się to przydaje, szczególnie na rozmowach kwalifikacyjnych 🙂 Dlatego bardzo zachęcam do samodzielnej zabawy z różną kolejnością działań.

W programie pominąłem jeszcze ostatni operator unarny: zaprzeczenie. Odnosi się on jednak do zmiennych typu logicznego (boolean). Jednak o nich oraz o zmiennych typu tekstowego napiszę już w kolejnym poście na “Drodze programisty”.

1 reply

Trackbacks & Pingbacks

  1. […] używaliśmy funkcji. Zobacz teraz na poprzednie posty z kodem pisanym w języku Java (na przykład tu lub tu) i zwróć proszę uwagę na to, że jest jedna główna funkcja. To jest taka funkcja […]

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *