Вычисление чисел Фибоначчи, по всем, наверное, хорошо известному примитивному алгоритму. Для достаточно больших значений (>45) вычисляется очень долго. При реализации на С++ была идея перенести вычисления на стадию компиляции. Но! Обнаружилось что и сборка исходика, и выполнение делаются практически моментально и никак не похоже, что в это время что-то вычисляется. Хотя я считал, что компилироваться это должно очень долго. Почему так происходит?
#include <stdio.h>
#include <stdlib.h>
unsigned long long fib(unsigned long long n) {
if (n < 2) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
}
int main(int argc, char** argv) {
if (argc < 2) {
return EXIT_SUCCESS;
}
long long n = atoll(argv[1]);
unsigned long long res = fib(n < 0 ? -n : n);
if (n < 0 && (n % 2) == 0) {
printf("%lld\n", -res);
} else {
printf("%llu\n", res);
}
return EXIT_SUCCESS;
}
Это-же самое, переписанное на C++:
#include <cstdio>
#include <cstdlib>
#include <stdexcept>
template <int N> struct Fib { static const unsigned long long VALUE = Fib<N - 1>::VALUE + Fib<N - 2>::VALUE; };
template <> struct Fib<0> { static const unsigned long long VALUE = 0; };
template <> struct Fib<1> { static const unsigned long long VALUE = 1; };
#define FIB_V(n) (Fib<(n)>::VALUE)
unsigned long long fib(unsigned long long n) {
static const unsigned long long fib_nums[] = {
FIB_V(0), FIB_V(1), FIB_V(2), FIB_V(3), FIB_V(4), FIB_V(5), FIB_V(6), FIB_V(7), FIB_V(8), FIB_V(9),
FIB_V(10), FIB_V(11), FIB_V(12), FIB_V(13), FIB_V(14), FIB_V(15), FIB_V(16), FIB_V(17), FIB_V(18), FIB_V(19),
FIB_V(20), FIB_V(21), FIB_V(22), FIB_V(23), FIB_V(24), FIB_V(25), FIB_V(26), FIB_V(27), FIB_V(28), FIB_V(29),
FIB_V(30), FIB_V(31), FIB_V(32), FIB_V(33), FIB_V(34), FIB_V(35), FIB_V(36), FIB_V(37), FIB_V(38), FIB_V(39),
FIB_V(40), FIB_V(41), FIB_V(42), FIB_V(43), FIB_V(44), FIB_V(45), FIB_V(46), FIB_V(47), FIB_V(48), FIB_V(49),
FIB_V(50), FIB_V(51), FIB_V(52), FIB_V(53), FIB_V(54), FIB_V(55), FIB_V(56), FIB_V(57), FIB_V(58), FIB_V(59),
FIB_V(60), FIB_V(61), FIB_V(62), FIB_V(63), FIB_V(64), FIB_V(65), FIB_V(66), FIB_V(67), FIB_V(68), FIB_V(69),
FIB_V(70), FIB_V(71), FIB_V(72), FIB_V(73), FIB_V(74), FIB_V(75), FIB_V(76), FIB_V(77), FIB_V(78), FIB_V(79),
FIB_V(80), FIB_V(81), FIB_V(82), FIB_V(83), FIB_V(84), FIB_V(85), FIB_V(86), FIB_V(87), FIB_V(88), FIB_V(89),
FIB_V(90), FIB_V(91), FIB_V(92), FIB_V(93)
};
if (n < (sizeof(fib_nums) / sizeof(fib_nums[0]))) { return fib_nums[n]; }
else { throw std::overflow_error("overflow error"); }
}
int main(int argc, char** argv) {
if (argc < 2) {
return EXIT_SUCCESS;
}
long long n = std::atoll(argv[1]);
try {
unsigned long long res = fib(n < 0 ? -n : n);
if (n < 0 && (n % 2) == 0) {
std::printf("%lld\n", -res);
} else {
std::printf("%llu\n", res);
}
} catch (std::overflow_error const& e) {
std::printf("%s!\n", e.what());
}
return EXIT_SUCCESS;
}