From 24a82230626e986392bcba7dc86b80118aefcdc3 Mon Sep 17 00:00:00 2001 From: Pronay Debnath Date: Sat, 14 Oct 2023 00:53:30 +0530 Subject: [PATCH] Added [FEATURE REQUEST] Golden Ration formula to find Nth Fibonacci number #4505 (#4513) * Create FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Create FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumber.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update FibonacciNumber.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciNumber.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Delete src/main/java/com/thealgorithms/maths/FibonacciNumberTest.java * Create FibonacciNumberTest.java * Update FibonacciNumber.java * Update FibonacciNumberTest.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumberTest.java * Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Create FibonacciCalculator.java * Update FibonacciNumberTest.java * Update and rename FibonacciCalculator.java to FibCalc.java * Update FibonacciNumberTest.java * Update FibCalc.java * Update FibonacciNumber.java * Delete src/test/java/com/thealgorithms/maths/FibCalc.java * Create FibCalc.java * Update FibonacciNumberTest.java * Update FibCalc.java * Update FibonacciNumberTest.java * Update FibonacciNumber.java * Update FibonacciNumberTest.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumber.java * Update FibonacciNumberTest.java * Update FibonacciNumber.java * fix: use proper name * fix: use proper class name * tests: add `returnsCorrectValues` * Update and rename FibCalc.java to Fibonacci.java * Update Fibonacci.java * Update FibonacciNumber.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update Fibonacci.java * Update FibonacciNumber.java * Update and rename FibCalcTest.java to FibonacciTest.java * Update FibonacciNumber.java * Update Fibonacci.java * Update Fibonacci.java * Update Fibonacci.java * Update FibonacciTest.java * Update Fibonacci.java * Update src/main/java/com/thealgorithms/maths/Fibonacci.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update FibonacciTest.java * Update FibonacciNumberTest.java * Update FibonacciNumberTest.java * Update FibonacciTest.java * Update src/main/java/com/thealgorithms/maths/Fibonacci.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/test/java/com/thealgorithms/maths/FibonacciTest.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/Fibonacci.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update FibonacciNumber.java * Update FibonacciNumber.java * Update Fibonacci.java * Update FibonacciNumber.java * Update and rename FibonacciNumber.java to FibonacciNumberGoldenRation.java * Update and rename FibonacciNumberTest.java to FibonacciNumberGoldenRationTest.java * Update Fibonacci.java * Update FibonacciNumberGoldenRation.java * Update FibonacciNumberGoldenRationTest.java * Update FibonacciTest.java * Update Fibonacci.java * Update FibonacciNumberGoldenRationTest.java * Update FibonacciNumberGoldenRationTest.java * Update FibonacciNumberGoldenRation.java * Update FibonacciNumberGoldenRation.java * Update FibonacciNumberGoldenRationTest.java * Update FibonacciNumberGoldenRationTest.java * Update src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> * Update and rename Fibonacci.java to FibonacciLoop.java * Update FibonacciNumberGoldenRation.java * Update FibonacciNumberGoldenRationTest.java * Update and rename FibonacciTest.java to FibonacciLoopTest.java * Update FibonacciLoop.java * Update FibonacciLoop.java * Update FibonacciNumberGoldenRation.java * docs: add missing dot --------- Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com> Co-authored-by: vil02 --- .../thealgorithms/maths/FibonacciLoop.java | 41 +++++++++++++++ .../maths/FibonacciNumberGoldenRation.java | 50 +++++++++++++++++++ .../maths/FibonacciLoopTest.java | 36 +++++++++++++ .../FibonacciNumberGoldenRationTest.java | 29 +++++++++++ 4 files changed, 156 insertions(+) create mode 100644 src/main/java/com/thealgorithms/maths/FibonacciLoop.java create mode 100644 src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java create mode 100644 src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java create mode 100644 src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java diff --git a/src/main/java/com/thealgorithms/maths/FibonacciLoop.java b/src/main/java/com/thealgorithms/maths/FibonacciLoop.java new file mode 100644 index 000000000..de23a4305 --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/FibonacciLoop.java @@ -0,0 +1,41 @@ +package com.thealgorithms.maths; + +import java.math.BigInteger; + +/** + * This class provides methods for calculating Fibonacci numbers using BigInteger for large values of 'n'. + */ +public final class FibonacciLoop { + + private FibonacciLoop() { + // Private constructor to prevent instantiation of this utility class. + } + + /** + * Calculates the nth Fibonacci number. + * + * @param n The index of the Fibonacci number to calculate. + * @return The nth Fibonacci number as a BigInteger. + * @throws IllegalArgumentException if the input 'n' is a negative integer. + */ + public static BigInteger compute(final int n) { + if (n < 0) { + throw new IllegalArgumentException("Input 'n' must be a non-negative integer."); + } + + if (n <= 1) { + return BigInteger.valueOf(n); + } + + BigInteger prev = BigInteger.ZERO; + BigInteger current = BigInteger.ONE; + + for (int i = 2; i <= n; i++) { + BigInteger next = prev.add(current); + prev = current; + current = next; + } + + return current; + } +} diff --git a/src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java b/src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java new file mode 100644 index 000000000..4df37a40f --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java @@ -0,0 +1,50 @@ +package com.thealgorithms.maths; + +/** + * This class provides methods for calculating Fibonacci numbers using Binet's formula. + * Binet's formula is based on the golden ratio and allows computing Fibonacci numbers efficiently. + * + * @see Binet's formula on Wikipedia + */ +public final class FibonacciNumberGoldenRation { + private FibonacciNumberGoldenRation() { + // Private constructor to prevent instantiation of this utility class. + } + + /** + * Compute the limit for 'n' that fits in a long data type. + * Reducing the limit to 70 due to potential floating-point arithmetic errors + * that may result in incorrect results for larger inputs. + */ + public static final int MAX_ARG = 70; + + /** + * Calculates the nth Fibonacci number using Binet's formula. + * + * @param n The index of the Fibonacci number to calculate. + * @return The nth Fibonacci number as a long. + * @throws IllegalArgumentException if the input 'n' is negative or exceeds the range of a long data type. + */ + public static long compute(int n) { + if (n < 0) { + throw new IllegalArgumentException("Input 'n' must be a non-negative integer."); + } + + if (n > MAX_ARG) { + throw new IllegalArgumentException("Input 'n' is too big to give accurate result."); + } + + if (n <= 1) { + return n; + } + + // Calculate the nth Fibonacci number using the golden ratio formula + final double sqrt5 = Math.sqrt(5); + final double phi = (1 + sqrt5) / 2; + final double psi = (1 - sqrt5) / 2; + final double result = (Math.pow(phi, n) - Math.pow(psi, n)) / sqrt5; + + // Round to the nearest integer and return as a long + return Math.round(result); + } +} diff --git a/src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java b/src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java new file mode 100644 index 000000000..93aec3976 --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java @@ -0,0 +1,36 @@ +package com.thealgorithms.maths; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.math.BigInteger; +import org.junit.jupiter.api.Test; + +public class FibonacciLoopTest { + @Test + public void checkValueAtZero() { + assertEquals(BigInteger.ZERO, FibonacciLoop.compute(0)); + } + + @Test + public void checkValueAtOne() { + assertEquals(BigInteger.ONE, FibonacciLoop.compute(1)); + } + + @Test + public void checkValueAtTwo() { + assertEquals(BigInteger.ONE, FibonacciLoop.compute(2)); + } + + @Test + public void checkRecurrenceRelation() { + for (int i = 0; i < 100; ++i) { + assertEquals(FibonacciLoop.compute(i + 2), FibonacciLoop.compute(i + 1).add(FibonacciLoop.compute(i))); + } + } + + @Test + public void checkNegativeInput() { + assertThrows(IllegalArgumentException.class, () -> { FibonacciLoop.compute(-1); }); + } +} diff --git a/src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java b/src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java new file mode 100644 index 000000000..e3f7bf3e0 --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java @@ -0,0 +1,29 @@ +package com.thealgorithms.maths; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.math.BigInteger; +import org.junit.jupiter.api.Test; + +public class FibonacciNumberGoldenRationTest { + + @Test + public void returnsCorrectValues() { + for (int n = 0; n <= FibonacciNumberGoldenRation.MAX_ARG; ++n) { + final var actual = FibonacciNumberGoldenRation.compute(n); + final var expected = FibonacciLoop.compute(n); + assertEquals(expected, BigInteger.valueOf(actual)); + } + } + + @Test + public void throwsIllegalArgumentExceptionForNegativeInput() { + assertThrows(IllegalArgumentException.class, () -> { FibonacciNumberGoldenRation.compute(-1); }); + } + + @Test + public void throwsIllegalArgumentExceptionForLargeInput() { + assertThrows(IllegalArgumentException.class, () -> { FibonacciNumberGoldenRation.compute(FibonacciNumberGoldenRation.MAX_ARG + 1); }); + } +}