如何在没有小数位限制的情况下在C ++中制作浮点数

How to make a float in c++ without a decimal place limit

我有一个计算 Pi 的 c++ 程序,但由于存储 Pi 的浮点数的小数位限制,它的值在小数点后被截断。

我已经尝试使用不同的数据类型而不是浮点数,但它们的小​​数位限制仍然太小。

#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;
}

如何取消限制或使用一种方法来存储 Pi 的值而不在小数点后被截断?

(我忽略了@JAntonioPerez 在他的精彩回答中指出的一些不太基本的问题,并专注于我认为是这个问题的核心内容。)

如果您只需要更多的小数位精度,请使用 doublelong double 而不是 float

如果你想要更高的精度,或者可以指定为run-time或compile-time任意值的精度,那么你需要其他东西.或者:

  1. 使用arbitrary-precision数字数据类型;这里有一个 list 提供此类类型的库。
  2. 不是迭代整个数字,而是使用迭代来确定输出中个体 digits/characters 的值;并将您获得的数字一次一个(或一次几个)写入输出文件。

当然,这两个选项都相当复杂,可能不适合您所写的"toy program"。

这里有几个大问题。首先是您使用 std::cout 打印值,而 std::cout 默认只打印 6 位数字。第二个是您将 Pi 声明为 int64_t。这意味着您将获得最多 1 位数的精度,因为 Pi 是一个整数。您需要将其设置为浮点类型。

那么你会从每种类型中得到多少位数?

  • 来自 float
  • 的 6 位数字
  • 15-16 位来自 double
  • clang 和 gcc 上 long double 的 20 位数字,但 Visual Studio
  • 中只有 15-16 位
  • 来自 GCC __float128 的大约 30 位数字,尽管那一位仅适用于 GCC

如果你想要比这更高的精度,你将不得不使用一个 high-precision 算术库,它通过模拟给你更多的数字。它不会那么快,但它会完成工作。

您可以使用此代码了解每种类型的精度。我在类型上模板化了 calculatePi,所以你可以坚持使用 floatdoublelong double__float128。它将打印 20 位数字。此代码应正确打印 __float128 的所有 20 位数字。

#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); 
}