刚刚看过 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;
}