问题
我正在尝试实现快速浮点 = log2(float)。我编写了一个简单的 C 程序来将我的结果与 log2 进行比较,我得到了一个我找不到源的小错误。
背景
我正在采用识别浮点表示(忽略符号位)的方法是2^(exponent) * 1.significand
. 使用我得到的日志属性log2(float) = exp + log2(1.significand)
。最终我将截断表查找的有效数字,但现在我想验证正确的结果。
有关此灵感的进一步背景阅读:http: //www.icsi.berkeley.edu/pubs/techreports/TR-07-002.pdf
代码
问题就在这里。这是一个简单的程序,它提取浮点位并将指数添加到 log2(有效数)。
#include <math.h>
#include <stdint.h>
#include <stdio.h>
int main()
{
typedef union {
int32_t i;
float f;
} poly32_t;
float x = 31415926535.8;
poly32_t one;
one.f = 1.0f;
uint32_t ii;
uint32_t num_iter = 15;
for(ii=0; ii < num_iter; ++ii) {
poly32_t poly_x;
poly32_t poly_x_exponent;
poly32_t poly_x_significand;
// extract the exponent and significand
poly_x.f = x;
poly_x_significand.i = (0x007fffff & poly_x.i);
poly_x_exponent.i = (0xff & (poly_x.i >> 23) ) - 127;
// recover the hidden 1 of significand
poly_x_significand.f = 1.0 + ((float)poly_x_significand.i)/10000000;
// log2(2^exp * sig) = exponent + log2(significand)
float log_sig = log2(poly_x_significand.f);
float y_approx = (float)poly_x_exponent.i + log_sig;
// Get the actual value
float y_math = log2(x);
printf("math::log2(%16.4f)=%8.4f ; approx=%8.4f ; diff=%.4f\n",
x, y_math, y_approx, y_math-y_approx);
x *= 0.1;
}
return 1;
}
输出
math::log2(31415926784.0000)= 34.8708 ; approx= 34.7614 ; diff=0.1094
math::log2( 3141592576.0000)= 31.5488 ; approx= 31.4733 ; diff=0.0755
math::log2( 314159264.0000)= 28.2269 ; approx= 28.1927 ; diff=0.0342
math::log2( 31415926.0000)= 24.9050 ; approx= 24.7924 ; diff=0.1126
math::log2( 3141592.5000)= 21.5831 ; approx= 21.5036 ; diff=0.0794
math::log2( 314159.2500)= 18.2611 ; approx= 18.2221 ; diff=0.0390
math::log2( 31415.9258)= 14.9392 ; approx= 14.8235 ; diff=0.1158
math::log2( 3141.5925)= 11.6173 ; approx= 11.5340 ; diff=0.0833
math::log2( 314.1592)= 8.2954 ; approx= 8.2517 ; diff=0.0437
math::log2( 31.4159)= 4.9734 ; approx= 4.8546 ; diff=0.1188
math::log2( 3.1416)= 1.6515 ; approx= 1.5644 ; diff=0.0871
math::log2( 0.3142)= -1.6704 ; approx= -1.7187 ; diff=0.0483
math::log2( 0.0314)= -4.9924 ; approx= -4.9936 ; diff=0.0012
math::log2( 0.0031)= -8.3143 ; approx= -8.4050 ; diff=0.0907
math::log2( 0.0003)=-11.6362 ; approx=-11.6890 ; diff=0.0528
此时的“近似值”应该与 clib 的 log2 完全相同;任何帮助识别我的错误将不胜感激。