mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
Fix, Docs, Test: Fibonacci_fast (Renamed to Fibonacci_iterative)
(Sorry for long extended commit message) The original algorithm does not calculate the nth fibonacci number, but rather the next fibonacci number after storing it in a static variable. Thus, I abstracted the looping part out of the code that you have to write upon application, into the function itself. The function also does not calculate the nth fibonacci number, but rather the (n+1)th fibonacci number. The "Test" in main does not really test anything, rather demonstrates what it does. Added actual unit tests with test cases. The file brief did not explain what it actually does properly.
This commit is contained in:
parent
6376bf46af
commit
c676e02b4c
@ -1,57 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Faster computation of Fibonacci series
|
|
||||||
*
|
|
||||||
* An efficient way to calculate nth fibonacci number faster and simpler than
|
|
||||||
* \f$O(n\log n)\f$ method of matrix exponentiation This works by using both
|
|
||||||
* recursion and dynamic programming. as 93rd fibonacci exceeds 19 digits, which
|
|
||||||
* cannot be stored in a single long long variable, we can only use it till 92nd
|
|
||||||
* fibonacci we can use it for 10000th fibonacci etc, if we implement
|
|
||||||
* bigintegers. This algorithm works with the fact that nth fibonacci can easily
|
|
||||||
* found if we have already found n/2th or (n+1)/2th fibonacci It is a property
|
|
||||||
* of fibonacci similar to matrix exponentiation.
|
|
||||||
*
|
|
||||||
* \author [Krishna Vedala](https://github.com/kvedala)
|
|
||||||
* @see fibonacci_large.cpp, fibonacci.cpp, string_fibonacci.cpp
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* maximum number that can be computed - The result after 93 cannot be stored
|
|
||||||
* in a `uint64_t` data type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAX 93
|
|
||||||
|
|
||||||
/** Algorithm */
|
|
||||||
uint64_t fib(uint64_t n) {
|
|
||||||
static uint64_t f1 = 1,
|
|
||||||
f2 = 1; // using static keyword will retain the values of
|
|
||||||
// f1 and f2 for the next function call.
|
|
||||||
|
|
||||||
if (n <= 2)
|
|
||||||
return f2;
|
|
||||||
if (n >= 93) {
|
|
||||||
std::cerr
|
|
||||||
<< "Cannot compute for n>93 due to limit of 64-bit integers\n";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t temp = f2; // we do not need temp to be static
|
|
||||||
f2 += f1;
|
|
||||||
f1 = temp;
|
|
||||||
|
|
||||||
return f2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Main function */
|
|
||||||
int main() {
|
|
||||||
// Main Function
|
|
||||||
for (uint64_t i = 1; i < 93; i++) {
|
|
||||||
std::cout << i << " th fibonacci number is " << fib(i) << std::endl;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
128
math/fibonacci_iterative.cpp
Normal file
128
math/fibonacci_iterative.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Iterative computation of the fibonacci series.
|
||||||
|
*
|
||||||
|
* An efficient way to calculate nth fibonacci number (F_n) faster and
|
||||||
|
* simpler than O(nlog n) method of matrix exponentiation using
|
||||||
|
* iteration.
|
||||||
|
*
|
||||||
|
* The 94th fibonacci number exceeds the size of ant unsigned 64-bit integer,
|
||||||
|
* causing it to overflow.
|
||||||
|
*
|
||||||
|
* According to Wolfram Alpha, the Fibonacci number function would be F_n,
|
||||||
|
* where n is the position of the number in the Fibonacci sequence.
|
||||||
|
*
|
||||||
|
* @see fibonacci_large.cpp, fibonacci.cpp, string_fibonacci.cpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cassert> /// For assert
|
||||||
|
#include <cstdint> /// For uint8_t, uint64_t
|
||||||
|
#include <exception> /// For std::invalid_argument
|
||||||
|
#include <iostream> /// For std::cout
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @namespace
|
||||||
|
* @brief Mathematical algorithms
|
||||||
|
*/
|
||||||
|
namespace math {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculates the nth fibonacci number iteratively.
|
||||||
|
* @param n nth Fibonacci number
|
||||||
|
* @return nth Fibonacci number
|
||||||
|
* @note F_n = 1 if n <= 2
|
||||||
|
* @warning n <= 93, because 93 is the maximum value of the Fibonacci sequence
|
||||||
|
* that fits in a 64-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
uint64_t fibonacci(uint8_t n) {
|
||||||
|
const uint8_t fibonacciMax = 93;
|
||||||
|
|
||||||
|
// By definition, when n <= 2, F_n = 1
|
||||||
|
if (n <= 2) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > fibonacciMax) {
|
||||||
|
throw std::invalid_argument("Maximum value of n is 93.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value to return
|
||||||
|
uint64_t f1 = 1;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Temporary values.
|
||||||
|
uint64_t temp = 0, f2 = 1;
|
||||||
|
|
||||||
|
// 2-indexed because if i < 2, you end up finding F_(n + 2 - i)
|
||||||
|
// instead of F_n.
|
||||||
|
for (uint8_t i = 2; i < n; ++i) {
|
||||||
|
temp = f1;
|
||||||
|
f1 += f2;
|
||||||
|
f2 = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace math
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Self-test implementations to test fibonacci function.
|
||||||
|
* @note There is 1 special case: n <= 2
|
||||||
|
* @note There is 1 exceptional case: n > 93
|
||||||
|
*/
|
||||||
|
static void test() {
|
||||||
|
// Special test case.
|
||||||
|
std::cout << "Special case tests:\n"
|
||||||
|
"Input: 1\n"
|
||||||
|
"Expected output: 1\n\n";
|
||||||
|
assert(math::fibonacci(1) == 1);
|
||||||
|
|
||||||
|
std::cout << "Input: 2\n"
|
||||||
|
"Expected output: 1\n\n";
|
||||||
|
assert(math::fibonacci(2) == 1);
|
||||||
|
|
||||||
|
// Small test case.
|
||||||
|
std::cout << "Small case test:\n"
|
||||||
|
"Input: 10\n"
|
||||||
|
"Expected output: 55\n\n";
|
||||||
|
assert(math::fibonacci(10) == 55);
|
||||||
|
|
||||||
|
// Medium test case.
|
||||||
|
std::cout << "Medium case test:\n"
|
||||||
|
"Input: 45\n"
|
||||||
|
"Expected output: 1134903170\n\n";
|
||||||
|
assert(math::fibonacci(45) == 1134903170);
|
||||||
|
|
||||||
|
// Max test case.
|
||||||
|
// Note: Throws a warning because the value is greater than INT64_MAX. Still
|
||||||
|
// fits in UINT64_MAX, though.
|
||||||
|
std::cout << "Max case test:\n"
|
||||||
|
"Input: 93\n"
|
||||||
|
"Expected output: 12200160415121876738\n\n";
|
||||||
|
assert(math::fibonacci(93) == 12200160415121876738);
|
||||||
|
|
||||||
|
// Exception test case.
|
||||||
|
std::cout << "Exception case tests:\n"
|
||||||
|
"Input: 93\n"
|
||||||
|
"Expected output: Exception thrown successfully.\n"
|
||||||
|
"Result: ";
|
||||||
|
try {
|
||||||
|
math::fibonacci(94);
|
||||||
|
} catch (std::invalid_argument& e) {
|
||||||
|
std::cout << "Exception thrown successfully \nContent: " << e.what()
|
||||||
|
<< "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "All tests passed successfully.";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main function
|
||||||
|
* @returns 0 on exit
|
||||||
|
*/
|
||||||
|
int main() {
|
||||||
|
test();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user