Strona główna » Algorytmy » Teoria Liczb » Ciąg geometryczny
 

Ciąg geometryczny

Definicja

Ciąg geometryczny to taki ciąg liczbowy o skończonej lub nieskończonej liczbie wyrazów. Każdy wyraz, prócz pierwszego, jest iloczynem wyrazu poprzedniego oraz stałej wartości q, która jest nazywana ilorazem ciągu. Rekurencyjny wzór na n-ty wyraz ciągu to . Iloraz q, o ile jest różny od 0, można wyliczyć ze wzoru .

Implementacja

n-ty wyraz ciągu

Dowolny wyraz ciągu można wyznaczyć na kilka sposobów. Jeden z nich polega na rekurencyjnym wyznaczeniu wyrazu zgodnie ze wzorem :

  1. double wyrazN_rekurencja(double a1, double q, int n) {
  2.   if (n == 1) return a1;
  3.   return q * wyrazN_rekurencja(a1, q, n - 1);
  4. }

(1.) Funkcja wyrazN_rekurencja() przyjmuje kolejno a1 - wartość pierwszego wyrazu ciągu, q - wartość ilorazu oraz n - numer wyrazu do wyznaczenia. (2.) Jeśli numer wyrazu n to 1 to zwróć wartość pierwszego wyrazu. W przeciwnym razie (3.) zwróć poprzedni wyraz pomnożony przez iloraz. Takie rozwiązanie podaje prawidłowy wynik, ale można też skorzystać z wzoru . Wtedy rozwiązanie sprowadza się do jednej linijki i użycia funkcji pow() z biblioteki cmath:

  1. double wyrazN(double a1, double q, int n) {
  2.   return a1 * pow(q, n - 1);
  3. }

Czy ciąg jest geometryczny?

Mając nawet niewielką ilość wyrazów nie zawsze jest oczywiste czy dany ciąg jest ciągiem geometrycznym. Podczas pisania algorytmu wykonującego to zadanie należy pamiętać, że . Innymi słowy wystarczy obliczyć iloraz drugiego wyrazu do pierwszego, a następnie sprawdzić czy wyliczona wartość jest prawdziwa dla każdej kolejnej pary wyrazów:

  1. bool czyGeometryczny_proste(double* data, int n) {
  2.   double q = data[1] / data[0];
  3.   for (int i = 2; i < n; i++)
  4.     if (data[i] / data[i - 1] != q)
  5.       return false;
  6.   return true;
  7. }

(1.) Funkcja czyGeometryczny_proste() przyjmuje data - listę wyrazów ciągu oraz n - ile elementów ma lista data. Program (2.) wylicza iloraz drugiego wyrazu do pierwszego, a następnie (3.) sprawdza czy wynosi tyle samo dla (4.) każdej kolejnej pary liczb czy iloraz wynosi tyle samo. Jeśli tak nie jest to (5.) zwrócony zostanie fałsz. Jeśli pętla nie zostanie przerwana to program (6.) zwróci prawdę.

Warto jednak zastanowić się nad różnymi przypadkami ciągu, ponieważ mogą w nim wystąpić zera. Powyższy program nie napotka problemu jeśli podzieli 0 przez a, ale napotka problem kiedy podzieli a przez 0. Z tego powodu algorytm nie zadziała dla każdych danych wejściowych. Można to poprawić dodając odpowiednie warunki jaka jest wartość q jeśli w parze będzie jedno lub dwa zera. Jednak istnieje możliwość, aby pominąć dodatkowe warunki. Należy wtedy skorzystać z własności samych wyrazów, że środkowy wyraz jest średnią geometryczną wyrazów sąsiednich tj. . W ten sposób można sprawdzić czy ciąg jest geometryczny bez wyznaczania ilorazu q:

  1. bool czyGeometryczny_wzor(double* data, int n) {
  2.   for (int i = 1; i + 1 < n; i++)
  3.     if (data[i] * data[i] != data[i - 1] * data[i + 1])
  4.       return false;
  5.   return true;
  6. }

W obydwu przypadkach należy jednak pamiętać, że mogą wystąpić błędy zaokrąglenie liczb rzeczywistych. To może wpływać na błędne rozpoznawanie czy ciąg jest geometryczny.

Suma n wyrazów

Tak samo jak w poprzednich przypadkach tak samo w tym nie trzeba używać wzorów matematycznych, aby to osiągnąć. Sumując n pierwszych wyrazów wystarczy:

  1. double sumaNwyrazow_proste(double a1, double q, int n) {
  2.   double suma = a1;
  3.   for (int i = 1; i < n; i++){
  4.     a1 *= q;
  5.     suma += a1;
  6.   }
  7.   return suma;
  8. }

(2.) Początkowo suma jest ustawiona na wartość pierwszego wyrazu i (3.) dodawane są wartości kolejnych wyrazów. (4.) Wartość a1 jest mnożona przez q, aby uzyskać kolejny wyraz, aby go (5.) dodać do sumy. Na koniec (7.) zwrócona zostaje wartość suma.

Oczywiście w przypadku liczenia sumy ciągu geometrycznego można skorzystać ze wzoru: . Należy w tym przypadku jednak pamiętać, że dzielnik nie może być równy zero, więc należy sprawdzić czy q jest różne od jeden:

  1. double sumaNwyrazow_wzor(double a1, double q, int n) {
  2.   if (q == 1)
  3.     return a1 * n;
  4.   return a1 * ((1 - pow(q, n)) / (1 - q));
  5. }

(2.) Jeśli podany ciąg ma q = 1 to znaczy, że jest stały, więc wystarczy (3.) zwrócić pierwszą wartość pomnożoną przez n. Jednak dla każdego innego q zwrócony zostanie wynik (4.) zgodny z podanym wcześniej wzorem.

Testowanie funkcji

Powyższe funkcje można przetestować przy pomocy poniższej funkcji main():

  1. int main() {
  2.   cout << "Podaj pierwszy wyraz ciagu, jego iloraz oraz ktory wyraz zwrocic:\n";
  3.   double a1, q;
  4.   int n;
  5.   cin >> a1 >> q >> n;
  6.   cout << n << " wyraz to " << wyrazN(a1, q, n) << endl;
  7.   cout << "suma pierwszych 10 wyrazow wynosi " << sumaNwyrazow_wzor(a1, q, 10) << endl << endl;
  8.   cout << "Podaj z ilu wyrazow sklada sie ciag, a potem wpisz tyle liczb\n";
  9.   cin >> n;
  10.   double* data = new double[n];
  11.   for (int i = 0; i < n; i++)
  12.     cin >> data[i];
  13.   cout << "podany ciag " << (czyGeometryczny_wzor(data, n) ? "" : "nie ") << "jest geometryczny" << endl << endl;
  14.   delete[] data;
  15.   system("pause");
  16.   return 0;
  17. }
Zadania

Zadanie 1

Napisz program, który wczyta od użytkownika ciąg liczb. Jeśli wprowadzony ciąg będzie geometryczny to program powinien wypisać jego iloraz q na ekran.

Zadanie 2

Napisz program, który wczyta od użytkownika pierwszy wyraz ciągu oraz jego iloraz q oraz liczby n i k, a następnie wypisze na ekranie n kolejnych wyrazów ciągu począwszy od k-tego.