значение натурального логарифма - PullRequest
0 голосов
/ 27 июля 2010

Я хочу найти значение In (x) без использования функции math.h

Я следую формуле, которую я нашел в своей книге по математике:

log(m) base e = 2[ (m-1/m+1) + (1/3) * (m-1/m+1)^3 + (1/5) * (m-1/m+1)^5 + ... ]

Вот мойкод:

i = 3;
logx = 0 ;
ty = (x-1)/(x+1) ;
do
{
    logx = logx + ty ;
    tty = ty ;
    ty = (ty * ((x-1)/(x+1)) * ((x-1)/(x+1))) / i ;
    i = i + 2 ;
} while(tty - ty > 0.0000005 );
logx = 2*logx ;
printf("\n ln (%g) = %g \n", x, logx);

но это показывает ln(2) = 0.691916 вместо 0.693147 и ln(3) = 1.08765 вместо 1.098612 и т. д. Что не так?

Ответы [ 5 ]

4 голосов
/ 27 июля 2010

Фактически, что вычисляет OP:

$ 2 \ sum_ {n = 1, n \ text {odd}} ^ \ infty \ frac1 {n !!} \ left (\ frac{m-1} {m + 1} \ right) ^ n = \ sqrt {2 \ pi} \ exp \ left (\ frac12 \ left (\ frac {m-1} {m + 1} \ right) ^ 2\ right) \ operatorname {erf} \ left (\ frac1 {\ sqrt2} \ frac {m-1} {m + 1} \ right) $ http://mathcache.appspot.com/?tex=%5cpng%5c%5b2%5Csum_%7Bn%3D1%2Cn%5Ctext%7B%20odd%7D%7D%5E%5Cinfty%5Cfrac1%7Bn%21%21%7D%5Cleft%28%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%5Cright%29%5En%20%3D%20%5Csqrt%7B2%5Cpi%7D%20%5Cexp%5Cleft%28%5Cfrac12%5Cleft%28%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%5Cright%29%5E2%5Cright%29%5Coperatorname%7Berf%7D%5Cleft%28%5Cfrac1%7B%5Csqrt2%7D%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%5Cright%29%5c%5d

вместо

$ 2 \ sum_ {n = 1, n \ text {odd}} ^ \ infty \ frac1 {n} \ left (\ frac {m-1} {m + 1} \ right) ^ n =2 \ tanh ^ {- 1} \ frac {m-1} {m + 1} = \ ln m $ http://mathcache.appspot.com/?tex=%5cpng%5c%5b2%5Csum_%7Bn%3D1%2Cn%5Ctext%7B%20odd%7D%7D%5E%5Cinfty%5Cfrac1%7Bn%7D%5Cleft%28%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%5Cright%29%5En%20%3D%202%5Ctanh%5E%7B-1%7D%5Cfrac%7Bm-1%7D%7Bm%2b1%7D%20%3D%20%5Cln%20m%5c%5d

Кстати, лучше выделить ((x-1)/(x+1)) * ((x-1)/(x+1)), чтобы избежать его повторного вычисления.(Компилятор может или не может обработать это как инвариант цикла и удалить его.)

double ty = (x-1)/(x+1);
double p = ty * ty;
int i = 1;
double logx = 0;
do {
  logx += ty / i;
  tty = ty;
  ty *= p;
  i += 2;
} while (tty/(i-2) - ty/i > 5e-6);
4 голосов
/ 27 июля 2010

Вы не должны делить на i и затем назначать на ty, делить на i после добавления, то есть logx = logx + ty / i.

Редактировать это должно работать:

i=1;   // (i.e. not 3)
logx = 0 ;
ty = (x-1)/(x+1) ;
do
{
    logx = logx + ty / i;
    tty = ty ;
    ty = (ty * ((x-1)/(x+1)) * ((x-1)/(x+1)));
    i = i + 2 ;
} while(tty - ty > 0.0000005 );
1 голос
/ 27 июля 2010

Ваша реализация C неверна для алгоритма.

log(m) base e = 2[ (m-1/m+1) + (1/3) * (m-1/m+1)^3 + (1/5) * (m-1/m+1)^5 + ... ]
                                ^^^ what is this      ^^^ and this

Ваш алгоритм:

i = 3;
logx = 0 ;
ty = (x-1)/(x+1) ;
do
{
    logx = logx + ty ;
    tty = ty ;
    ty = (ty * ((x-1)/(x+1)) * ((x-1)/(x+1))) / i ; 
//  ^^ when i = 3 ty after this line = ((x-1)/(x+1) * ((x-1)/(x+1))^2) / 3
//     when i = 5 ty after this line = ((((x-1)/(x+1)^3) / 3) * ((x-1)/(x+1))^2) / 5 
//                                   = ((x-1)/(x+1)^5) / 15 <<< wrong divisor (see above, should be 5)
//     and it gets worse for each iteration of the loop
    i = i + 2 ;
} while(tty - ty > 0.0000005 );
logx = 2*logx ;
printf("\n ln (%g) = %g \n", x, logx);
0 голосов
/ 27 июля 2010

ISTR о том, что скорость сходимости логарифмических рядов заведомо низкая.

0 голосов
/ 27 июля 2010

вы аппроксимируете функцию с конечным числом итераций (условие остановки tty-ty> ...); уменьшите 0,00000005 и получите лучшую точность

тогда вы можете столкнуться с проблемами числовой точности, поэтому попробуйте использовать double вместо float, если вы этого еще не сделали

наконец, помните, что, как правило, логарифмы являются иррациональными числами, поэтому они просто не могут быть представлены конечным числом цифр

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...