Strona główna » Algorytmy » Artykuły » Cykliczny Licznik
 

Cykliczny Licznik

Wstęp

Bardzo często w Informatyce stosuje się liczniki, które posiadają wartości z pewnego określonego zakresu. Najprostszym przykładem jest zegarek: zarówno minuty jak i sekundy zmieniają się z zakresu od 0 do 59. Z kolei godziny od 0 do 23. W tym artykule przedstawione zostaną dwa różne podejścia do tego zadanienia.

Implementacja

Instrukcja warunkowa

Przyjmijmy, że implementujemy licznik, który będzie zachowywał się jak minuty w zegarze. Rozpoczynamy od wartości 0, a potem po wartości 59 jest ponownie 0. Jednym ze sposobów jest zastosowanie instrukcji warunkowej. W ten sposób po osiągnięciu pewnej wartości wartość jest zmieniana z powrotem na 0, a nie powiększana o 1.

C++
C#
  1.   if (licznik >= 59) {
  2.     licznik = 0;
  3.   } else {
  4.     licznik = licznik + 1;
  5.   }

Jest to rozwiązanie bardzo łatwe do zmodyfikowania. Pozwala również dodać różne inne warunki. Przykładowo gdybyśmy chcieli 'cofać' czas to wystarczyłoby dodać, że dla wartości poniżej 0 wartość ma zostać ustawiona na 59.

Funkcja modulo

Innym sposobem na stworzenia licznika cyklicznego jest zastosowanie funkcji modulo. Jest to operacja, która zwraca resztę z dzielenia a przez b. Przykładowo, aby zwiększać wartość o 1 wystarczy następujący kod:

C++
C#
  1.   licznik = (licznik + 1) % 60;

Powyższy kod nie uwzględnia zmniejszania licznika. Nie wymaga to jednak dopisywania dodatkowego warunku jak w przypadku instrukcji warunkowej. Jak wiadomo nieważne ile razy do a dodamy wartość b to reszta z dzielenia a + k·b przez b wciąż będzie się równać reszcie a przez b. W takim razie do pomniejszonej wartości wystarczy dodać b, aby otrzymać wartość dodatnią.

C++
C#
  1.   licznik = (licznik - 1 + 60) % 60;

Przedstawiony kod będzie działał prawidłowo niezależnie od tego czy wartość licznika będzie zwiększana o jeden czy zmniejszana o 1.

Modulo - Dowolny Zakres

Przedstawione wcześniej sposoby na zmianę wartości licznika przy pomocy funkcji modulo dotyczą jedynie zakresu od 0 do n. Jednak istnieje sposób, aby otrzymać wartości np. z zakresu od 1 do 10.

C++
C#
  1.   licznik = (licznik % 10) + 1;

W przedstawionym zapisie mylące może być to, że znikło dodawanie wartości 1 do licznika, a 1 jest dodawane do reszty z dzielenia przez 10. Otóż aktualną wartość licznika należy sprowadzić do zakresu 0 .. n + 1 poprzez odjęcie dolnego zakresu zmian zmiennej. Wtedy otrzymane licznik + 1 - 1 upraszcza się do licznik. Potem musimy dokonać reszty z dzielenia przez 10, aby ewentualnie licznik zaczął liczyć od nowa. Otrzymany wynik jest z zakresu 0 .. n, więc dodajemy dolny zakres zmiany licznika, aby ponownie otrzymać z określonego zakresu: tutaj z [1, 10].

W celu dokładniejszego wyjaśnienia warto przypatrzeć się kolejnemu zapisowi, który zmienia wartość licznika pomiędzy z zakresu [10, 30].

C++
C#
  1.   licznik = ((licznik - 9) % 21) + 10;

W tym przypadku od wartości licznik odejmujemy 9, bo licznik + 1 - 10. Dzielimy przez 21, ponieważ w podanym zakresie jest dokładnie 21 różnych wartości i na koniec dodajemy dolny zakres 10.

Zadania

Zadanie 1

Napisz program, który wczyta od użytkownika czas: godzinę, minutę, sekundę oraz upływa czasu do zasymulowania wyrażony w sekundach. Następnie wypisz na ekran, która będzie godzina po upływie wczytanej wartości sekund. Zakładamy, że zegarek jest 24 godzinny.

Przykładowo po wczytaniu czasu 10:10:10 i upływu równego 3661 sekund program powinien wypisać:

  1. 11:11:11

Zadanie 2

Napisz funkcję zmienWartosc(), która przyjmie następujące argumenty: wartosc - aktualna wartość licznika, min - minimalna wartość zmiennej, max - maksymalna wartość zmiennej oraz zmiana - określa o ile ma zostać zmieniona wartość zmiennej. Funkcja powinna zwrócić wartosc z dodaną wartością zmiana przy założeniu, że licznik zmienia się w zakresie [min, max]. Prztestuj działanie programu wczytując od użytkownika początkową wartość licznika, zakres zmiennej, o ile będzie zmieniany licznik i ile razy.

Przykładowo po wczytaniu początkowej wartości licznika 1, zakresu [1, 9] i zmianie 2 wykonanej 10 razy program powinien wypisać:

  1. 1 3 5 7 9 2 4 6 8 1