使用泰勒级数不是最简单的方法,也不是最简单的方法。大多数专业实现都使用近似多项式。我将向您展示如何使用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