且不談FP,如果n是個常量,在C++裡可以寫個模板在編譯期直接搞定,算是最佳化到極致了吧。算是C++模板超程式設計(template meta-programming)技術的小試牛刀。
template<int T> struct acc_ {
enum { result = N + acc_<N - 1>::result };
};
template<> struct acc_<0> {
enum { result = 0 };
使用:
int sum = acc_<1234>::result;
透過這種方式,acc_<1234>::result 會在編譯時直接被替換為常量,無任何執行時開銷。模板本身也不會產生任何額外二進位制程式碼。
藉助boost裡的if_之類的,這個實現還能更簡單。
當然,這個應該不是題主期望的答案,因為和FP無關。
我不知道題主這裡說的FP語言具體指哪個,但是一般來講,這樣的求和,如果是遞迴求解的話,屬於尾遞迴呼叫,會被編譯器最佳化,不會導致任何額外的棧增長。n作為值型別,且是右值,往往是分配在棧上,而不是堆上,會隨著棧的增減快速清除,並不存在GC的問題。 比如erlang:
acc(0) -> 0;
acc(N) when N > 0 -> N + acc(N - 1);
和C++模板的方式幾乎一模一樣(但這個是執行期求值),並不存在什麼儲存浪費和GC問題。
所以,如果嚴格的談“編譯最佳化技術”,基於以上,可以總結出兩點:
題外話,對於等差數列,可以直接用求和公式: f(n) = (1 + n) * n / 2
且不談FP,如果n是個常量,在C++裡可以寫個模板在編譯期直接搞定,算是最佳化到極致了吧。算是C++模板超程式設計(template meta-programming)技術的小試牛刀。
template<int T> struct acc_ {
enum { result = N + acc_<N - 1>::result };
};
template<> struct acc_<0> {
enum { result = 0 };
};
使用:
int sum = acc_<1234>::result;
透過這種方式,acc_<1234>::result 會在編譯時直接被替換為常量,無任何執行時開銷。模板本身也不會產生任何額外二進位制程式碼。
藉助boost裡的if_之類的,這個實現還能更簡單。
當然,這個應該不是題主期望的答案,因為和FP無關。
我不知道題主這裡說的FP語言具體指哪個,但是一般來講,這樣的求和,如果是遞迴求解的話,屬於尾遞迴呼叫,會被編譯器最佳化,不會導致任何額外的棧增長。n作為值型別,且是右值,往往是分配在棧上,而不是堆上,會隨著棧的增減快速清除,並不存在GC的問題。 比如erlang:
acc(0) -> 0;
acc(N) when N > 0 -> N + acc(N - 1);
和C++模板的方式幾乎一模一樣(但這個是執行期求值),並不存在什麼儲存浪費和GC問題。
所以,如果嚴格的談“編譯最佳化技術”,基於以上,可以總結出兩點:
編譯期常量合併(constant folding, constant propagation);尾呼叫消除(tail-call elimination)。題外話,對於等差數列,可以直接用求和公式: f(n) = (1 + n) * n / 2