Ниже код вычисляет числа Фибоначчи с помощью экспоненциально медленного алгоритма:Как время компиляции может быть (экспоненциально) быстрее, чем время выполнения?
#include <cstdlib>
#include <iostream>
#define DEBUG(var) { std::cout << #var << ": " << (var) << std::endl; }
constexpr auto fib(const size_t n) -> long long
{
return n < 2 ? 1: fib(n - 1) + fib(n - 2);
}
int main(int argc, char *argv[])
{
const long long fib91 = fib(91);
DEBUG(fib91);
DEBUG(fib(45));
return EXIT_SUCCESS;
}
И я расчета 45-го числа Фибоначчи во время выполнения, и 91st один во время компиляции.
Интересный факт состоит в том, что GCC 4.9 компилирует код и вычисляет fib91
в доли секунды, но требуется некоторое время, чтобы выплюнуть fib(45)
.
Мой вопрос: если GCC достаточно умен, чтобы оптимизировать вычисление fib(91)
, а не принимать экспоненциально медленный путь, что мешает ему делать то же самое для fib(45)
?
Означает ли это, что GCC создает две скомпилированные версии функции fib
, где одна быстро, а другая экспоненциально медленная?
Вопрос заключается в том не как компилятор оптимизирует fib(91)
расчета (да! Это действительно использует свой род запоминание), но, если он знает, как оптимизировать функции fib
, почему это не сделать то же самое для fib(45)
? И есть ли две отдельные компиляции функции fib
? Один медленный, а другой быстрый?
Этот вопрос требует знать как минимум флаги, используемые для компиляции программы – Jack
О первой части, 'const long long fib91 = fib (91);' вычисляется во время компиляции, вся функция заменяется фактическим значением , не уверен, почему это не делает это для fib45 – OneOfOne
Вероятно, '45' превышает предел рекурсии. играйте с '-fconstexpr-depth = Max_Recursion_Limit', чтобы узнать, превышен ли этот предел. – 101010