Я написал очень простую программу в C (вычисление PI), и я получил результат следующим образом: 3.1406174152499528235728265546100601568468846380710601806640625
Результат не выглядит как правильный PI, тогда я нашел код в Python в Интернете. Я запустил его и получил что-то вроде этого: 3.1415926535897932384626433832795028841971693993751058209749 - Правильный PI.
Затем я реализовал алгоритм Python в C точно так же, и я получил такой результат: 3.1406174152499528235728265546100601568468846380710601806640625
Почему результаты Python и C из одного и того же алгоритма настолько различны и как исправить код C, чтобы получить правильный результат?
Код Python:
from decimal import*
precision = 100
getcontext().prec = 100
a = 1
b = Decimal(1) / Decimal(2).sqrt()
t = Decimal(1) / Decimal(4)
p = 1
pi = 0
for x in range(0, precision):
nextA = (a + b) / 2
nextB = (a * b).sqrt()
nextT = t - p * ((a - nextA) ** 2)
nextP = 2 * p
pi = ((a + b) ** 2) / (4 * t)
a,b,t,p = nextA,nextB,nextT,nextP
print pi
C код:
long double a = 1;
long double b = 1/sqrt(2);
long double t = 0.25;
long double p = 1;
long double an, bn, tn, pn, myPI;
long int x;
for(x = 0; x < 100; x++)
{
an = (a + b) / 2;
bn = sqrt(a * b);
tn = t - p * ((a - an) * (a - an));
pn = 2 * p;
myPI = ((a + b) * (a + b)) / (4 * t);
a = an; b = bn; t = tn; p = tn;
}
printf("%.61Lf\n", myPI);
return 0;
Проблема заключается в опечатке в вашем коде, p = tn;
должно быть p = pn;
,
Примечание: для длинных удвоений используйте sqrtl
.
Обновление: если вы распечатываете аппроксимацию для pi после каждой итерации, после пятой итерации она не улучшается, и только первые 20 цифр верны. для большей точности вам нужны лучшие (не встроенные) типы данных.
Вы запрашиваете больше точности, чем могут предоставить переменные с плавающей запятой C. Вы должны использовать произвольную арифметику точности, а не плавучую точку с фиксированной точностью. Или, по крайней мере, используйте арифметику с фиксированной точностью с прецизионным значением, превышающим требуемую точность вычислений. Код Python устанавливает точность до 100 для достижения этого.
Ну, @yi_H также обнаружил ошибку в вашем коде, но даже если вы исправите то, что вы не получите такой же точности от вашего кода C, как и от вашего кода Python, по причинам, указанным выше.
Причина в том, что числа с плавающей запятой (обычно 80 бит) являются наиболее точными числовыми типами данных C, которые должны предлагать готовые и для большинства вычислений в реальном мире более чем достаточно (OTOH, float, независимо от того, насколько велика, не может точно представить 0,85, например, но в стороне).
Python имеет встроенный большой целочисленный тип, который позволяет ему представлять произвольно большие целые числа (и, поддерживая эту реализацию, произвольно точные рациональные числа). Используя их, можно вычислить приближения PI, которые гораздо точнее, чем что-либо, что может содержать float.
Если вы хотите еще большей точности, вам нужно будет найти алгоритм, который вычисляет цифры один за другим и выплевывает их при вычислении.
long double
- это точность около 80 двоичных цифр.