- a. Przebieg procedury Herona uzależnić od Epsilon
public class HeronSquareRoot {
public static double heronSquareRoot(double x, double epsilon) {
if (x < 0) {
throw new IllegalArgumentException("Liczba musi być większa lub równa 0.");
}
double guess = x; // Inicjalizacja początkowej wartości odgadnięcia
int iteration = 0; // Licznik iteracji
while (Math.abs(guess * guess - x) > epsilon) {
guess = 0.5 * (guess + x / guess); // Aktualizacja odgadnięcia
iteration++;
}
System.out.println("Liczba iteracji: " + iteration);
return guess;
}
public static void main(String[] args) {
double x = 16.0; // Liczba, której pierwiastek chcemy obliczyć
double epsilon = 0.0001; // Wartość epsilon
double sqrt = heronSquareRoot(x, epsilon);
System.out.println("Pierwiastek kwadratowy z " + x + " wynosi: " + sqrt);
}
}
- b. Przebieg procedury Herona uzależnić od N (ilości kroków)
public class HeronSquareRoot {
public static double heronSquareRoot(double x, int N) {
if (x < 0) {
throw new IllegalArgumentException("Liczba musi być większa lub równa 0.");
}
double guess = x; // Inicjalizacja początkowej wartości odgadnięcia
for (int i = 0; i < N; i++) {
guess = 0.5 * (guess + x / guess); // Aktualizacja odgadnięcia
}
return guess;
}
public static void main(String[] args) {
double x = 16.0; // Liczba, której pierwiastek chcemy obliczyć
int N = 10; // Ilość kroków (liczba iteracji)
double sqrt = heronSquareRoot(x, N);
System.out.println("Pierwiastek kwadratowy z " + x + " po " + N + " krokach wynosi: " + sqrt);
}
}
a. Wyznaczyć dokładny wzór opisujący ilość kroków niezbędnych do obliczenia (fib n)
W algorytmie iteracyjnym wzór na ilość kroków to n - 1, ponieważ zaczynamy od 0 i wykonujemy n - 1 iteracji, aby obliczyć n-tą liczbę Fibonacciego.
W rekurencyjnym liczba kroków wynosi około 2^n.
Jeśli chcesz obliczyć dokładną ilość kroków dla danego n, musiałbyś przeanalizować rekurencyjną strukturę algorytmu Fibonacciego i policzyć liczbę wywołań funkcji rekurencyjnych dla danego n. Można to zrobić przy użyciu technik dynamicznego programowania lub memoizacji, aby uniknąć wielokrotnego obliczania tych samych wartości. Wtedy ilość kroków będzie dokładnie zależała od n, ale nadal będzie to rosnąca funkcja wykładnicza.
b. Zaproponować procedurę rekurencyjną fib, która generuje proces iteracyjny
public class Fibonacci {
public static long fib(int n) {
return fibHelper(n, 0, 1);
}
private static long fibHelper(int n, long a, long b) {
if (n == 0) {
return a;
} else if (n == 1) {
return b;
} else {
return fibHelper(n - 1, b, a + b);
}
}
public static void main(String[] args) {
int n = 10;
long result = fib(n);
System.out.println("Fibonacci(" + n + ") = " + result);
}
}
c. Zastosować formę (recur ...) i policzyć Fib(10000)
W Javie, ze względu na ograniczenia stosu rekursji, obliczanie Fib(10000) za pomocą rekurencji w formie recur byłoby nieefektywne i prowadziłoby do przepełnienia stosu. Jest to wynik ogromnej liczby wywołań rekurencyjnych, co skutkuje błędem "StackOverflowError".
Zapewne to zadanie ma Wam pokazać ten problem i powinniście te obliczenia zrobić iteracyjnie:
import java.math.BigInteger;
public class Fibonacci {
public static BigInteger fib(int n) {
BigInteger a = BigInteger.ZERO;
BigInteger b = BigInteger.ONE;
for (int i = 2; i <= n; i++) {
BigInteger next = a.add(b);
a = b;
b = next;
}
return b;
}
public static void main(String[] args) {
int n = 10000;
BigInteger result = fib(n);
System.out.println("Fibonacci(" + n + ") = " + result);
}
}