64,690
社区成员
发帖
与我相关
我的任务
分享
看起来好像很别扭, 还是这样吧:
double mLog( double x )
{
int N , i;
double r = 0. , x0;
assert( x > 0 );
N = (int)((*(int64*)&x) >> 52) - 1022;
(*(int64*)&x) -= (int64)N << 52;
if( ((*(int64*)&x) & FRACMASK ) == 0 )
return (N-1) * LOG2;
x0 = x = (1-x)/(1+x); /* 0 < x < .333... */
for( i = 1; x0 > 1e-18; i+=2 , x0 *= x * x )
r += x0 / i;
return 2 * -r + N * LOG2;
}
这个精度和速度应该都够了:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#define LOG2 (0.69314718055994529)
#ifdef _MSC_VER
typedef __int64 int64;
#define FRACMASK (0xFFFFFFFFFFFFFI64)
#else
typedef long long int64;
#define FRACMASK (0xFFFFFFFFFFFFFLL)
#endif
double mLog( double x )
{
int N , i;
double r = 0. , x0;
assert( x > 0 );
N = (int)((*(int64*)&x) >> 52) - 1022;
(*(int64*)&x) -= (int64)N << 52;
if( ((*(int64*)&x) & FRACMASK ) == 0 )
return (N-1) * LOG2;
x0 = x = (x-1)/(x+1); /* -.333... < x0 < 0 */
for( i = 1; x0 < -1e-18; i+=2 , x0 *= x * x )
r += x0 / i;
return 2 * r + N * LOG2;
}
int main()
{
double x , r1 , r2;
for( x = .000000001; x < 10000000; x *= 10 )
{
r1 = mLog( x );
r2 = log ( x );
printf( "%.8g : %.8g %.8g %.8g\n" , x , r1 , r2 , r1 - r2 );
}
for( x = .0001234567; x < 10000; x *= 1.234567 )
{
r1 = mLog( x );
r2 = log ( x );
printf( "%.8g : %.8g %.8g %.8g\n" , x , r1 , r2 , r1 - r2 );
}
return 0;
}