如果你真正需要的是
ceil(12 * log2(/* something */))
再有是一個非常簡單的O(1)計算,它將使用一個只有12個值的表格。
使用frexp()將值分成指數和尾數。 (這只是位操作,所以它只需要幾個週期。)
查看尾數在預先計算的2.0根據第12根(除以2)的權力列表中,你可以用最多四次比較。
結果是12 *(指數-1)+最小根的指數> =尾數。
編輯補充:
有實際上是一個更好的解決方案,因爲兩個十二根的權力得到合理均勻分佈。如果將[0.5,1.0)(由frexp返回的尾數範圍)劃分爲17個均勻間隔的子範圍,則每個子範圍將落入兩個可能的返回值之一。因此,如果將每個子範圍與索引關聯到根矢量中,則只需將目標(在該範圍內)與單個根進行比較。
這是爲時已晚,我寫連貫的英語,所以你必須解決下面的代碼:
int Ceil12TimesLog2(double x) {
int exp;
double mantissa = std::frexp(x, &exp) * 2;
int idx = indexes[int((mantissa - 1.0) * 17)];
return 12 * (exp - 1) + (mantissa <= roots[idx] ? idx : idx + 1);
}
// Here are the reference tables.
double roots[12] = {
0x1.0000000000000p+0,
0x1.0f38f92d97963p+0,
0x1.1f59ac3c7d6c0p+0,
0x1.306fe0a31b715p+0,
0x1.428a2f98d728bp+0,
0x1.55b8108f0ec5ep+0,
0x1.6a09e667f3bccp+0,
0x1.7f910d768cfb0p+0,
0x1.965fea53d6e3dp+0,
0x1.ae89f995ad3adp+0,
0x1.c823e074ec129p+0,
0x1.e3437e7101344p+0
};
int indexes[17] = { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11 };
我想這一點,並從約0.5秒帶來的總計算時間減少(對於log2f )到約0.15秒,使用OP中的環路。參考表的總大小是164字節。
你在用k做什麼?您發佈的代碼沒有副作用或輸出。 – BCoates
注意在你開始做複雜的東西之前:log((f-0.5)/ fk)= log(f-0.5)-log(fk),這樣你就可以分別計算這些問題,從而將問題減少到1000 + 11000日誌計算。這可以將日誌計算的數量減少約1000倍。 – Bitwise
@同時,我剛纔發佈了一個答案。 (比您的評論輕鬆13秒。) –