Как реализовать натуральный логарифм с непрерывной дробью в C?

Здесь у меня маленькая проблема. Создайте что-нибудь из этой формулы:

Это то, что у меня есть, но это не работает. Фрэнки, я действительно не понимаю, как это должно работать.. Я пытался закодировать это с некоторыми плохими инструкциями. N - число итераций и частей дроби. Я думаю, что это приводит к рекурсии, но не знаю как.

Спасибо за любую помощь.

double contFragLog(double z, int n)
{
    double cf = 2 * z;
    double a, b;
    for(int i = n; i >= 1; i--)
    {
        a = sq(i - 2) * sq(z);
        b = i + i - 2;
        cf = a / (b - cf);

    }
    return (1 + cf) / (1 - cf);
}

2 ответа

Решение

Центральный цикл перепутан. Переработанный. Рекурсия тоже не нужна. Просто сначала вычислите самый глубокий термин и выходите.

double contFragLog(double z, int n) {
  double zz = z*z;
  double cf = 1.0;  // Important this is not 0
  for (int i = n; i >= 1; i--) {
    cf = (2*i -1) - i*i*zz/cf;
  }
  return 2*z/cf;
}

void testln(double z) {
  double y = log((1+z)/(1-z));
  double y2 = contFragLog(z, 8);
  printf("%e %e %e\n", z, y, y2);
}

int main() {
  testln(0.2);
  testln(0.5);
  testln(0.8);
  return 0;
}

Выход

2.000000e-01 4.054651e-01 4.054651e-01
5.000000e-01 1.098612e+00 1.098612e+00
8.000000e-01 2.197225e+00 2.196987e+00

[Редактировать]

По подсказке @MicroVirus, я нашел double cf = 1.88*n - 0.95; работать лучше чем double cf = 1.0;, Поскольку используется больше терминов, используемое значение имеет меньшую разницу, но хороший начальный cf требует меньше сроков для хорошего ответа, особенно для |z| около 0,5 Больше работы может быть сделано здесь, когда я учился 0 < z <= 0.5, @MicroVirus предложение 2*n+1 может быть близко к моему предложению из-за n является.

Это основано на обратном вычислении и отмечении ценности CF[n] как n выросла. Я был удивлен, что значение "seed" не оказалось каким-то хорошим целочисленным уравнением.

Вот решение проблемы, которая использует рекурсию (если кому-то интересно):

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

/* `i` is the iteration of the recursion and `n` is
   just for testing when we should end. 'zz' is z^2 */
double recursion (double zz, int i, int n) {
  if (!n)
    return 1;

  return 2 * i - 1 - i * i * zz / recursion (zz, i + 1, --n);
}

double contFragLog (double z, int n) {
  return 2 * z / recursion (z * z, 1, n);
}

void testln(double z) {
  double y = log((1+z)/(1-z));
  double y2 = contFragLog(z, 8);
  printf("%e %e %e\n", z, y, y2);
}

int main() {
  testln(0.2);
  testln(0.5);
  testln(0.8);
  return 0;
}

Вывод идентичен решению выше:

2.000000e-01 4.054651e-01 4.054651e-01
5.000000e-01 1.098612e+00 1.098612e+00
8.000000e-01 2.197225e+00 2.196987e+00
Другие вопросы по тегам