使用泰勒級數不是最簡單的方法,也不是最簡單的方法。大多數專業實現都使用近似多項式。我將向您展示如何使用Remez algorithm在Maple(這是一個計算機代數程序)中生成一個。
對於精度的3位數字在Maple執行以下命令:
with(numapprox):
Digits := 8
minimax(ln(x), x = 1 .. 2, 4, 1, 'maxerror')
maxerror
其響應是以下多項式:
-1.7417939 + (2.8212026 + (-1.4699568 + (0.44717955 - 0.056570851 * x) * x) * x) * x
隨着最大誤差:0。000061011436
我們生成近似於所述LN(x)的多項式,但是隻有[1..2]區間內。增加間隔並不明智,因爲這會增加最大誤差。取而代之的是,請執行下列操作分解:
所以先找2的最大功率,這仍然比數量更小(參見:What is the fastest/most efficient way to find the highest set bit (msb) in an integer in C?)。這個數字實際上是以2爲底的對數。除以該值,則結果進入1..2區間。最後,我們將不得不添加n * ln(2)來獲得最終結果。
的示例實現對於數字> = 1:
float ln(float y) {
int log2;
float divisor, x, result;
log2 = msb((int)y); // See: https://stackoverflow.com/a/4970859/6630230
divisor = (float)(1 << log2);
x = y/divisor; // normalized value between [1.0, 2.0]
result = -1.7417939 + (2.8212026 + (-1.4699568 + (0.44717955 - 0.056570851 * x) * x) * x) * x;
result += ((float)log2) * 0.69314718; // ln(2) = 0.69314718
return result;
}
雖然如果打算只在[1.0,2.0]區間使用它,則該函數是這樣的:
float ln(float x) {
return -1.7417939 + (2.8212026 + (-1.4699568 + (0.44717955 - 0.056570851 * x) * x) * x) * x;
}
當你有這樣的限制,你應該問自己什麼是你可以接受的精度?那麼可接受的誤差幅度是多少? – 2012-03-21 05:29:09
@YochaiTimmer:忘了補充。感謝提醒。我編輯了我的問題。 :) – Donotalo 2012-03-21 05:37:27
另外,什麼是輸入和輸出數字格式?定點如8.8?這聽起來像你將通過存儲相對於273開爾文的偏移量,即攝氏度而受益。 – Potatoswatter 2012-03-21 05:38:00