mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Add fibonacci Binet's formula.
This commit is contained in:
parent
a23400380d
commit
51d67e7eac
@ -61,7 +61,7 @@ a set of rules that precisely define a sequence of operations.
|
|||||||
* **Math**
|
* **Math**
|
||||||
* `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, multiplication/division by two, make negative etc.
|
* `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, multiplication/division by two, make negative etc.
|
||||||
* `B` [Factorial](src/algorithms/math/factorial)
|
* `B` [Factorial](src/algorithms/math/factorial)
|
||||||
* `B` [Fibonacci Number](src/algorithms/math/fibonacci)
|
* `B` [Fibonacci Number](src/algorithms/math/fibonacci) - classic and closed-form versions.
|
||||||
* `B` [Primality Test](src/algorithms/math/primality-test) (trial division method)
|
* `B` [Primality Test](src/algorithms/math/primality-test) (trial division method)
|
||||||
* `B` [Euclidean Algorithm](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD)
|
* `B` [Euclidean Algorithm](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD)
|
||||||
* `B` [Least Common Multiple](src/algorithms/math/least-common-multiple) (LCM)
|
* `B` [Least Common Multiple](src/algorithms/math/least-common-multiple) (LCM)
|
||||||
|
@ -17,4 +17,4 @@ The Fibonacci spiral: an approximation of the golden spiral created by drawing c
|
|||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
[Wikipedia](https://en.wikipedia.org/wiki/Fibonacci_number)
|
- [Wikipedia](https://en.wikipedia.org/wiki/Fibonacci_number)
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import fibonacciClosedForm from '../fibonacciClosedForm';
|
|
||||||
|
|
||||||
describe('fibonacciClosedForm', () => {
|
|
||||||
it('should calculate fibonacci correctly', () => {
|
|
||||||
expect(fibonacciClosedForm(1)).toBe(1);
|
|
||||||
expect(fibonacciClosedForm(2)).toBe(1);
|
|
||||||
expect(fibonacciClosedForm(3)).toBe(2);
|
|
||||||
expect(fibonacciClosedForm(4)).toBe(3);
|
|
||||||
expect(fibonacciClosedForm(5)).toBe(5);
|
|
||||||
expect(fibonacciClosedForm(6)).toBe(8);
|
|
||||||
expect(fibonacciClosedForm(7)).toBe(13);
|
|
||||||
expect(fibonacciClosedForm(8)).toBe(21);
|
|
||||||
expect(fibonacciClosedForm(20)).toBe(6765);
|
|
||||||
expect(fibonacciClosedForm(30)).toBe(832040);
|
|
||||||
expect(fibonacciClosedForm(50)).toBe(12586269025);
|
|
||||||
expect(fibonacciClosedForm(70)).toBe(190392490709135);
|
|
||||||
expect(fibonacciClosedForm(71)).toBe(308061521170129);
|
|
||||||
expect(fibonacciClosedForm(72)).toBe(498454011879264);
|
|
||||||
expect(fibonacciClosedForm(73)).toBe(806515533049393);
|
|
||||||
expect(fibonacciClosedForm(74)).toBe(1304969544928657);
|
|
||||||
expect(fibonacciClosedForm(75)).toBe(2111485077978050);
|
|
||||||
});
|
|
||||||
});
|
|
@ -19,5 +19,7 @@ describe('fibonacciNth', () => {
|
|||||||
expect(fibonacciNth(73)).toBe(806515533049393);
|
expect(fibonacciNth(73)).toBe(806515533049393);
|
||||||
expect(fibonacciNth(74)).toBe(1304969544928657);
|
expect(fibonacciNth(74)).toBe(1304969544928657);
|
||||||
expect(fibonacciNth(75)).toBe(2111485077978050);
|
expect(fibonacciNth(75)).toBe(2111485077978050);
|
||||||
|
expect(fibonacciNth(80)).toBe(23416728348467685);
|
||||||
|
expect(fibonacciNth(90)).toBe(2880067194370816120);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
import fibonacciNthClosedForm from '../fibonacciNthClosedForm';
|
||||||
|
|
||||||
|
describe('fibonacciClosedForm', () => {
|
||||||
|
it('should throw an error when trying to calculate fibonacci for not allowed positions', () => {
|
||||||
|
const calculateFibonacciForNotAllowedPosition = () => {
|
||||||
|
fibonacciNthClosedForm(76);
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(calculateFibonacciForNotAllowedPosition).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate fibonacci correctly', () => {
|
||||||
|
expect(fibonacciNthClosedForm(1)).toBe(1);
|
||||||
|
expect(fibonacciNthClosedForm(2)).toBe(1);
|
||||||
|
expect(fibonacciNthClosedForm(3)).toBe(2);
|
||||||
|
expect(fibonacciNthClosedForm(4)).toBe(3);
|
||||||
|
expect(fibonacciNthClosedForm(5)).toBe(5);
|
||||||
|
expect(fibonacciNthClosedForm(6)).toBe(8);
|
||||||
|
expect(fibonacciNthClosedForm(7)).toBe(13);
|
||||||
|
expect(fibonacciNthClosedForm(8)).toBe(21);
|
||||||
|
expect(fibonacciNthClosedForm(20)).toBe(6765);
|
||||||
|
expect(fibonacciNthClosedForm(30)).toBe(832040);
|
||||||
|
expect(fibonacciNthClosedForm(50)).toBe(12586269025);
|
||||||
|
expect(fibonacciNthClosedForm(70)).toBe(190392490709135);
|
||||||
|
expect(fibonacciNthClosedForm(71)).toBe(308061521170129);
|
||||||
|
expect(fibonacciNthClosedForm(72)).toBe(498454011879264);
|
||||||
|
expect(fibonacciNthClosedForm(73)).toBe(806515533049393);
|
||||||
|
expect(fibonacciNthClosedForm(74)).toBe(1304969544928657);
|
||||||
|
expect(fibonacciNthClosedForm(75)).toBe(2111485077978050);
|
||||||
|
});
|
||||||
|
});
|
@ -1,11 +0,0 @@
|
|||||||
/**
|
|
||||||
* Calculate fibonacci number at specific position using closed form function.
|
|
||||||
*
|
|
||||||
* @param n n-th number of fibonacci sequence (must be number from 1(inclusive) to 75(inclusive))
|
|
||||||
* @return {number}
|
|
||||||
*/
|
|
||||||
export default function fibonacciClosedForm(n) {
|
|
||||||
const sqrt5 = Math.sqrt(5);
|
|
||||||
const phi = (1 + sqrt5) / 2;
|
|
||||||
return Math.floor((phi ** n) / sqrt5 + 0.5);
|
|
||||||
}
|
|
23
src/algorithms/math/fibonacci/fibonacciNthClosedForm.js
Normal file
23
src/algorithms/math/fibonacci/fibonacciNthClosedForm.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Calculate fibonacci number at specific position using closed form function (Binet's formula).
|
||||||
|
* @see: https://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression
|
||||||
|
*
|
||||||
|
* @param {number} position - Position number of fibonacci sequence (must be number from 1 to 75).
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
export default function fibonacciClosedForm(position) {
|
||||||
|
const topMaxValidPosition = 75;
|
||||||
|
|
||||||
|
// Check that position is valid.
|
||||||
|
if (position < 1 || position > topMaxValidPosition) {
|
||||||
|
throw new Error(`Can't handle position smaller than 1 or greater than ${topMaxValidPosition}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate √5 to re-use it in further formulas.
|
||||||
|
const sqrt5 = Math.sqrt(5);
|
||||||
|
// Calculate φ constant (≈ 1.61803).
|
||||||
|
const phi = (1 + sqrt5) / 2;
|
||||||
|
|
||||||
|
// Calculate fibonacci number using Binet's formula.
|
||||||
|
return Math.floor((phi ** position) / sqrt5 + 0.5);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user