Чтобы увидеть более точный вывод, вам нужно запросить больше точности, чем по умолчанию в C ++.Один из способов сделать это:
#include <iomanip>
…
std::cout << std::setprecision(99);
Далее, рассмотрите этот код:
for (i=1; i<=n; i++)
sum += 1.0/pow(2,i);
Во-первых, признайте, что качество реализаций pow
варьируется.Стандарты C и C ++ слабо оценивают качество операций с плавающей запятой, и некоторые реализации pow
возвращают результаты для простых случаев, таких как pow(10, 3)
, которые немного отличаются от математических результатов.Из-за того, что pow
часто применяется, pow(2, i)
может не страдать от этой проблемы, но это следует учитывать.
Предположим, pow(2, i)
точно вычисляет правильный результат.Предположим также, что ваша реализация C ++ использует общий базовый 32-битный двоичный формат IEEE-754 для float
.Если так, то нет ошибки в сумме, вычисленной выше для n
≤ 24.
Это связано с тем, что каждый член 1.0/pow(2, i)
представляется в виде одного бита в значении(дробная часть) float
, а float
имеет 24-битные значения, поэтому 24 последовательных бита могут быть представлены без ошибок.Как только вы увеличите точность, используемую для форматирования вывода, суммы, показанные для n
≤ 24, должны быть точными.
Когда n
= 25, сумма больше не помещается в float
.В этот момент математический результат будет округлен до ближайшего значения, представляемого в float
, обычно используя правило, согласно которому, если есть связь между двумя ближайшими представляемыми значениями, будет выбрано значение с четным младшим битом.Это означает, что результат будет 1, точно.Для всех n
> 24 результат будет 1.
. При использовании типа float
невозможно повысить точность выше этого.Это связано с тем, что из всех значений, которые могут быть представлены в типе float
, 1 - это значение, наиболее близкое к точной математической сумме ряда.Просто нет более близкого представимого значения, поэтому никакие вычисления или изменение исходного кода не могут дать более точного значения.
Вы можете получить более точные значения, используя double
вместо float
.Если для double
используется базовый 64-битный двоичный формат IEEE-754, то это даст точные результаты для n
≤ 53. Для n
> 53 результат снова будет равен 1, а сумма может бытьулучшается только при использовании арифметики с расширенной точностью.
Кроме того, обратите внимание, что:
float sum = 0;
for (i=1; i<=n; i++)
sum += 1.0/pow(2,i);
математически эквивалентно:
float sum = 1 - pow(2.f, (float) -n);