我写的一个程序:一个求以 2 为底的对数

刚刚看过 Knuth 的 << The Art Of Programming >> ,对一个习题很 有感觉,于是自己写了一个练习.

有一个问题没有解决, 就是具体把精度算到多少位合适,这里固定是 31 , 如果超过这个精度就有可能导致溢出,得到错误结果.

#include <stdio.h>
#include <assert.h>
#include <math.h>

static int countx(unsigned long a)
{
        int count=0;
        int x=1;
        if((*((long*)&a)) < 0) { // the most signification bit is set.
                count = ((sizeof(a)) <<3) -1 ;
                return count;
        }
        assert(a!=0);
        while(x<=a) {
                x <<=1;
                count ++;
        }
        return count-1;
}

double mylog(double y)
{
        int r = 0;
        double x = 0;
        int sign = 1;
        int n;
        int accurate;

        assert(y>0);
        if(y<1.0){
                sign = -1;
                y =1.0/y;
        }
        n = countx((unsigned long)y);
        x = (double)n;
        y /= (1L<<n);
        y *= y;
        r = 1;
call:
        if(y<=1.0){
                return (sign==1)?x:-x;
        }else if(y>1.0&&y<2.0){
                y *=y ;
        }else if(y>=2.0 && y < 4.0){
                x += 1.0 / ((double) (1<<r));
                y /= 2.0;
                y *=y;
        }else{
                assert(0);
        }
        r ++ ;
        if(r>31){
                return (sign==1)?x:-x;
        }
        goto call;
        return (sign==1)?x:-x;

}
int main (int argc, char * argv[])
{
        unsigned long i;
        double a[]={
                0.5,
                1.0,
                123456.0,
                12.0,
                16.0,
                160.0,
                1601.0,
                0.0
        };
        double *p=a;
        while(*p != 0.0){
                printf("%f %f\n",mylog(*p),log(*p)/log(2.0));
                p++;
        }
        return 0;
}