Использование длинного двойника или просто двойника для вычисления числа пи?

Я вычисляю пи, используя длинную формулу. Я пытаюсь лучше познакомиться с числами с плавающей запятой и т. Д. У меня есть рабочая программа, которая использует двойные числа. Проблема с моим кодом:

  1. Если я использую двойное число, число пи будет точным только до 7-го знака после запятой. Я не могу сделать это более точным.
  2. Если я использую длинное двойное значение, число пи будет точным до 9-го знака после запятой, однако выполнение кода займет гораздо больше времени. Если я проверяю точность менее 0,00000001 с помощью длинного двойного числа, число пи возвращает значение 9,4246775. Я предполагаю, что это связано с длинным двойником.

Мой вопрос в том, что является наиболее точным типом переменной? Как я могу изменить свой код, чтобы повысить точность числа пи?

Вот мой код:

#include <iomanip>
#include <cstdlib>
#include <iostream>
#include <cmath>

using namespace std;

int main()
{
 double arctan;
 double pi;
 double precision;
 double previous=0;
 int y=3;
 int loopcount=0;

   cout<<"Start\n";

   arctan=1-(pow(1,y)/y);

 do
   {
     y=y+2;
     arctan=arctan+(pow(1,y)/y);
     y=y+2;
     arctan=arctan-(pow(1,y)/y);

      pi=4*(arctan);

    //  cout<<"Pi is: ";
    //  cout<<setprecision(12)<<pi<<endl;

      precision=(pi*(pow(10,10)/10));

      loopcount++;

      if(precision-previous<0.000000001)
        break;

      previous=precision;
    }
  while(true);

  cout<<"Pi is:"<<endl;
       cout<<setprecision(11)<<pi<<endl;
  cout<<"Times looped:"<<endl;
       cout<<loopcount<<endl;

return 0;
}

person adohertyd    schedule 20.03.2012    source источник
comment
Вам следует подумать о переключении на представление с фиксированной точкой, если вы хотите жестко контролировать точность.   -  person Doug T.    schedule 21.03.2012
comment
Когда вы изменили на long double, вы изменили все вызовы API, например. pow() к powl(), arctan() к atanl()-эквиваленту и т. д.?   -  person sarnold    schedule 21.03.2012
comment
Дуг, не могли бы вы объяснить это? Я не знаком с этим.   -  person adohertyd    schedule 21.03.2012
comment
sarnold, я заменил все экземпляры double в своих переменных на long double. Однако я не переименовывал ни одну из переменных. Как это изменит ситуацию?   -  person adohertyd    schedule 21.03.2012
comment
Переименование переменных не будет иметь никакого значения, но вы должны будете использовать правильные методы (API) в соответствии с вашими типами переменных. Это то, что говорил Сарнольд.   -  person noMAD    schedule 21.03.2012
comment
Кроме того, с какой точностью вы этого хотите?   -  person noMAD    schedule 21.03.2012
comment
Я хочу, чтобы это было до 10 знаков после запятой или больше. Не понимал, что эти методы могут различаться между двойниками и длинными двойниками. рассмотрю это   -  person adohertyd    schedule 21.03.2012
comment
Почему вы хотите, чтобы это было до 10 знаков после запятой или больше? Кажется подозрительным, что вы получили 9 цифр и хотите еще одну. Почему бы просто не закодировать константу?   -  person John Zwinck    schedule 21.03.2012
comment
Это может быть 12, может быть 20... Как я уже сказал, я пытаюсь лучше понять работу с плавающей запятой и работу с ними, поэтому жесткое кодирование константы не совсем полезно. Я хочу знать, почему это работает до 9 без проблем, однако переход к 10 приводит к совершенно другому результату. Вот почему 10...   -  person adohertyd    schedule 21.03.2012
comment
@sarnold: Неправда. Это для кода C. В коде C++ есть перегруженная версия pow() для всех типов (потому что она может, а C — нет). Вам просто нужно убедиться, что вы используете заголовок C++: cplusplus.com/reference/clibrary /cmath/pow   -  person Martin York    schedule 21.03.2012
comment
Смотрите также: 26.4.7 complex value operations [complex.value.ops]   -  person Martin York    schedule 21.03.2012
comment
@Локи: Спасибо! Я не знал, что С++ позволяет перегружать функции/методы для примитивов. (Очевидно, я многого не знаю о C++.)   -  person sarnold    schedule 21.03.2012
comment
какой компилятор вы используете? Кроме того, могу ли я предложить вам проверить, что y не переполняется?   -  person Foon    schedule 12.01.2013
comment
pow(1,y)? какие? зачем снова и снова вычислять выражение, равное 1?   -  person phuclv    schedule 11.03.2016


Ответы (3)


Вы можете получить максимальные пределы двойных/длинных двойных значений из std::numeric_limits

#include <iostream>
#include <limits>

int main()
{
    std::cout << "     Double::digits10:  " << std::numeric_limits<double>::digits10 << "\n";
    std::cout << "Long Double::digits10:  " << std::numeric_limits<long double>::digits10 << "\n";
}

На моей машине это дает:

     Double::digits10:  15
Long Double::digits10:  18

Поэтому я ожидаю, что long double будет содержать до 18 цифр.
Определение этого термина можно найти здесь:

http://www.cplusplus.com/reference/std/limits/numeric_limits/

Стандартная цитата: 18.3.2 Numeric limits [limits]

Также обратите внимание: поскольку комментарий находится далеко внизу в приведенном выше списке:

Этот @sarnold неверен (хотя загадочным образом у него есть два глупых человека, которые голосуют за его комментарий, не проверяя) в своих утверждениях о pow(). То, что он утверждает, применимо только к C. C++ имеет перегрузки для типов, потому что в C++ pow() является шаблонной функцией. См.: http://www.cplusplus.com/reference/clibrary/cmath/pow/ в стандарте на 26.4.7 complex value operations [complex.value.ops]

person Martin York    schedule 21.03.2012
comment
Это отличный ответ, спасибо за это. Ничего не видел об этих ограничениях, и я много читал об этом. Спасибо за четкий ответ. - person adohertyd; 21.03.2012
comment
Быстрый вопрос для вас, хотя. Если long double имеет точность до 18 знаков, почему я получаю значение 9,454665... для pi после того, как изменю уровень точности на ‹0,000000001? - person adohertyd; 21.03.2012
comment
Какие значения на вашей машине. Эти значения не являются универсальными. - person Martin York; 21.03.2012
comment
Примечание. Это не точно до 18 мест. Это с точностью до 18 цифр (включая 3). Чем больше число выше десятичной точки, тем меньше цифр ниже десятичной точки вы получите. - person Martin York; 21.03.2012
comment
Начиная со стандарта 1999 г., C также имеет универсальные версии pow() и других функций из <tgmath.h>. Согласно стандарту 2011 года, _Generic позволяет пользователям писать аналогичные функции. - person Keith Thompson; 06.12.2012
comment
Преимущество использования std::numeric_limits заключается в том, что он адаптируется к настройкам компилятора, таким как те, которые позволили бы long double быть эквивалентным 128-битной плавающей запятой iEEE. - person cycollins; 23.07.2019

Предопределенный тип с плавающей запятой с наибольшей точностью — long double.

Существует три предопределенных типа с плавающей запятой:

  • float имеет по крайней мере 6 десятичных цифр точности
  • double имеет не менее 10 и не менее float
  • long double имеет не менее 10 и не менее double

Это минимальные требования; любой или все эти типы могут иметь большую точность.

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

person Keith Thompson    schedule 21.03.2012

Или вы можете просто жестко закодировать цифры PI и посмотреть, что произойдет. ^_^

http://www.joyofpi.com/pi.html

person Andy Finkenstadt    schedule 21.03.2012