Формула Лейбница для π / 4



Меня просят вывести суммирование формулы Лейбница до n-го члена ряда с точностью до 15 десятичных знаков. places.In исчисление, формула Лейбница для π задается:
1 - 1/3 + 1/5 -1/7 + ... = π/4



Это мой код



#include<stdio.h>
#include<math.h>
int main()
{
int n,i;
long double s=0;
scanf("%d",&n);
for(i=0;i<n;i++){
s+=(long double)pow(-1,i)/(2*i+1);
}
printf("%Lfn",s);
return 0;
}


Может ли кто-нибудь сказать мне, почему я не могу достичь точности до 15-го десятичного знака?
Моя цель не состоит в том, чтобы вывести значение pi / 4, я просто должен вывести суммирование для данного n
793   2  

2 ответов:

Вопрос: почему ... достичь точности до 15-го десятичного знака?
A: для отображения 15 десятичных знаков после десятичной точки используйте формат "%0.15f". Чтобы вычислить 15 десятичных знаков сходимости, как минимум, n должен быть очень большим.

Как упоминалось @user3386109, " ошибка в результате ограничена 1 / (2n+1)", поэтому потребуется около 5e14 итераций. (Приблизительная оценка: 10 дней на моем компьютере.) Как типичный double имеет точность около 1 части в pow (2,53) или 1 в 9e15, то достигаются пределы расчета double. Приведенный ниже код сравнивает порядок вычисления, чтобы уменьшить ошибку, но в лучшем случае , ошибка все равно будет составлять не менее 0,5 частей в 9e15.

Поскольку члены ряда колеблются около предела, при остановке после n итераций можно добавить конечную итерацию 1/2 следующей итерации. это позволило бы получить около 1 бита точности.

Как уже упоминалось, существуют и другие методы вычисления π, которые сходятся быстрее.


Обновлено в соответствии с хорошим наблюдением @user3386109.

При суммировании терминов код может суммировать их в различных порядках. Приведенные ниже методы 2 иллюстрируют, что скромно более стабильный результат достигается раньше, когда сначала суммируются малые члены вместе. Я ожидал бы в лучшем случае только 1 или 2 бит лучшего ответа.

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

//Leibniz formula for pi/4
typedef float fp;

fp LeibnizForward(unsigned n) {
  volatile fp sum = 0.0;
  fp sign = 1.0;
  unsigned i = 1;
  while (n-- > 0) {
    sum += sign / i;
    sign = -sign;
    i = (i + 2);
  }
  return sum;
}

fp LeibnizReverse(unsigned n) {
  volatile fp sum = 0.0;
  fp sign = 1.0;
  unsigned i = 2 * n - 1;
  if (n % 2 == 0)
    sign = -sign;
  while (n-- > 0) {
    sum += sign / i;
    sign = -sign;
    i = (i - 2);
  }
  return sum;
}

void PiTest(unsigned n) {
  printf("%u\n", n);
  static const fp pic = 3.1415926535897932384626433832795;
  const char *format = "%s %0.9f\n";
  printf(format, "pi-", nextafterf(pic,0));
  printf(format, "pi ", pic);
  printf(format, "pi+", nextafterf(pic,4));
  fp pif = LeibnizForward(n) * 4;
  printf(format, "pif", pif);
  fflush(stdout);
  fp pir = LeibnizReverse(n) * 4;
  printf(format, "pir", pir);
  fflush(stdout);
}

int main(void) {
  PiTest(0);
  PiTest(1);
  PiTest(10);
  PiTest(100);
  PiTest(1000);
  PiTest(10000);
  PiTest(100000);
  PiTest(1000000);
  PiTest(10000000);
  PiTest(100000000);

  return 0;
}

0
pi- 3.141592503
pi  3.141592741
pi+ 3.141592979
pif 0.000000000
pir 0.000000000
1
pi- 3.141592503
pi  3.141592741
pi+ 3.141592979
pif 4.000000000
pir 4.000000000
10
pi- 3.141592503
pi  3.141592741
pi+ 3.141592979
pif 3.041839600
pir 3.041839600
25
pi- 3.141592503
pi  3.141592741
pi+ 3.141592979
pif 3.181576490
pir 3.181576729
100
pi- 3.141592503
pi  3.141592741
pi+ 3.141592979
pif 3.131592512
pir 3.131592751
1000
pi- 3.14 1592503
pi  3.14 1592741
pi+ 3.14 1592979
pif 3.14 0592575
pir 3.14 0592575
10000
pi- 3.141 592503
pi  3.141 592741
pi+ 3.141 592979
pif 3.141 498566
pir 3.141 492605
100000
pi- 3.1415 92503
pi  3.1415 92741
pi+ 3.1415 92979
pif 3.1415 85827
pir 3.1415 82489
1000000
pi- 3.14159 2503
pi  3.14159 2741
pi+ 3.14159 2979
pif 3.14159 5364
pir 3.14159 1549
10000000
pi- 3.14159 2503 previous float
pi  3.14159 2741 machine float pi
pi+ 3.14159 2979 next float
pif 3.14159 6794
pir 3.14159 2503
100000000 Additional iterations do not improve the result.
pi- 3.14159 2503
pi  3.14159 2741 
pi+ 3.14159 2979
pif 3.14159 6794
pir 3.14159 2503
1000000000
pi- 3.14159 2503
pi  3.14159 2741
pi+ 3.14159 2979
pif 3.14159 6794
pir 3.14159 2503

Измените оператор printf, чтобы вывести больше значений после десятичной точки.

В качестве примера, используя

printf("%30.28Lf\n",s);

Выведет число на 28 знаков после запятой. С помощью n=25 я получил следующий результат.

0.7953941713587578038252220991

Comments

    Ничего не найдено.