Как сделать float в c ++ без ограничения десятичного знака - PullRequest
2 голосов
/ 12 мая 2019

У меня есть программа на С ++, которая вычисляет число Пи, но затем его значение обрезается после нескольких десятичных разрядов из-за предела десятичного знака в числе, в котором хранится число Пи.

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

#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

int main(){
    cout << "Calculate Pi using the Nilakantha series" << endl << endl;

    unsigned long int iterations = 0;
    unsigned long int x = 0;
    unsigned long int y = 2;
    char z = 0;
    string fileName = "";
    int64_t Pi = {3.0f};

    cout << "Input the number of loop iterations(maximum of 4,294,967,295): ";
    cin >> iterations;
    cout << "Input the name of the file you want to write to: ";
    cin >> fileName;

    for(x = 0; x < iterations; x++){
        Pi += 4.0f / (y * (y + 1.0f) * (y + 2.0f));
        y += 2;
        Pi -= 4.0f / (y * (y + 1.0f) * (y + 2.0f));
    y += 2;
    }

    ofstream file;
    file.open(fileName + ".txt");
    file << Pi;
    file.close();

    cout << endl << "Calculation complete, check the file " << fileName << ".txt";

    cin >> z;
}

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

Ответы [ 2 ]

3 голосов
/ 13 мая 2019

Здесь есть несколько больших проблем. Во-первых, вы используете std::cout для печати значения, а std::cout по умолчанию печатает только 6 цифр. Во-вторых, вы объявили Pi как int64_t. Это означает, что вы получите не более 1 цифры точности, поскольку Pi - целое число. Вы должны иметь его как тип с плавающей точкой.

Так сколько цифр вы получите от каждого типа?

  • 6 цифр от float
  • 15-16 цифр от double
  • 20 цифр от long double в clang и gcc, но только 15-16 в Visual Studio
  • Около 30 цифр от GCC __float128, хотя это работает только на GCC

Если вам нужна более высокая точность, вам придется использовать высокоточную арифметическую библиотеку, которая дает вам больше цифр, симулируя ее. Это будет не так быстро, но сработает.

Вы можете поиграть с точностью до каждого типа, используя этот код. Я настроил calculatePi на тип, так что вы можете просто вставить float, double, long double или __float128. Он напечатает 20 цифр. Этот код должен правильно печатать все 20 цифр для __float128.

#include <cstdio>
using namespace std;

template<class Float>
Float calculatePi(size_t iterations) {
    Float y = 2;
    Float Pi = 3;
    const Float two = 2;
    const Float four = 4;
    const Float one = 1;

    for(size_t i = 0; i < iterations; i++) {
        Pi += four / (y * (y + one) * (y + two));
        y += two;
        Pi -= four / (y * (y + one) * (y + two));
        y += two;
    }
    return Pi; 
}
int main(){
    long double result = calculatePi<long double>(1000000); 

    printf("Expected: 3.14159265358979323846\n"); 
    printf("Actual:   %.20Lf", result); 
}
2 голосов
/ 12 мая 2019

(Я игнорирую некоторые менее фундаментальные проблемы, на которые @JAntonioPerez указывает в своем прекрасном ответе, и сосредотачиваюсь на том, что я считаю основой этого вопроса.)

Если вам просто нужно еще несколько десятичных цифр точности, тогда используйте double или long double вместо float.

Если вы хотите намного более высокую точность или точность, которая может быть указана в качестве произвольного значения во время выполнения или во время компиляции, тогда вам нужно что-то еще. Или:

  1. Использовать тип данных числа с произвольной точностью; Вот список библиотек, предоставляющих такие типы.
  2. Вместо перебора всего числа используйте итерацию для определения значения отдельных цифр / символов в выводе; и запишите полученные вами цифры в выходной файл по одной (или несколько за раз).

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

...