Как рассчитать 37 десятичных знаков числа Эйлера в C? - PullRequest
0 голосов
/ 12 февраля 2020

У меня есть следующий код, и он возвращает: 2.7182818284590455348848081484902650118, где только 2.718281828459045 правильно, а остальные неверно.

Я использую следующую ссылку: 2.71828182845904523536028747135 * http://www.vaxasoftware.com/doc_edu/mat/nume15000.pdf

Мой код:

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

#define EPSILON 1.0e-15

int main() {
    unsigned long long fact = 1;
    double e = 2.0, e0;
    int n = 2;
    do {
        e0 = e;
        fact *= n++;
        e += 1.0 / fact;
    }
    while (fabs(e - e0) >= EPSILON);
    printf("e = %.37f\n", e);
    return 0;
}

Я ценю, если кто-нибудь может мне помочь. Большое вам спасибо!

Ответы [ 3 ]

1 голос
/ 12 февраля 2020

Мой код:

#include "gmp.h"

Просто включение этого заголовка не использует арифметику с высокой точностью c по волшебству; вам придется использовать соответствующие функции , как описано в руководстве GNU MP !

Например, вы должны использовать

{
  mpf_t x;
  mpf_init2 (x, 100);
  ...

. инициализировать с плавающей точкой x для точности 100 бит, а для вычислений вы будете использовать функции отсюда , такие как mpf_add, чтобы добавить 2 такие переменные.

1 голос
/ 12 февраля 2020

Как вычислить 37 десятичных знаков для Эйлера в C?

2 128 составляет около 3,4 * 10 38 . Формируя 128-битный целочисленный числитель / знаменатель, мы можем достичь желаемого e .

Переписав l oop, как показано ниже, и набрав достаточно большой n до num*i + 1 вот-вот переполнится (n == 33), мы можем прийти к нужному результату или приблизиться к нему.

// Algorithm
wide_floating_point e() {
  unsigned n = 33;
  my_uint128 num = 1;
  my_uint128 den = 1;
  for (unsigned i=1; i <= n; i++) {
    num = num*i + 1;
    den = den*i;
  }
  return (wide_floating_point) num/fact;
}

Теперь OP, возможно, не имеет целочисленного типа без знака 128 и не может выполнить 128 / 128-битное деление с плавающей запятой. Тем не менее, OP нужно только создать 2 функции (реализации не показаны, но по сути это математика начальной школы):

typedef struct {
  // or unsigned char decimal_digit[40] or 
  // however you want to save a big integer
  uint64_t hi,lo;
} my_uint128; 

my_uint128 times_add_128(my_uint128 x, unsigned m, bool a);
void print_quotient_128(my_uint128 num, my_uint128 dem);

Если мы проверяем алгоритм и используем __int128 и используем long double ( с точностью 80) мы приближаемся к цели.

long double e(int n) {
  unsigned __int128 fact = 1;
  unsigned __int128 num = 1;
  for (int i=1; i<=n; i++) {
    fact *= i;
    if (num >  (((unsigned __int128)-1)-1)/i) { printf("%d!\n", i); exit(0); }
    num = num*i + 1;
  }
  return 1.0L*num/fact;
}

int main() {
  for (int i=1; i<34; i++)  {
    printf("%d %.25Lf\n", i, e(i));
  }
}

   2,718281828459045235 3602874713526624977
33 2.718281828459045235 4281681

Я оставляю 2 функции times_add_128(), print_quotient_128() для OP, чтобы кодировать:

0 голосов
/ 12 февраля 2020

Я уменьшаю ваше значение в.

printf("e = %.37f\n", e);

до

printf("e = %.15f\n", e);

ответ:

2,718281828459046

...