如何在没有小数位限制的情况下在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 在他的精彩回答中指出的一些不太基本的问题,并专注于我认为是这个问题的核心内容。)
如果您只需要更多的小数位精度,请使用 double
或 long double
而不是 float
。
如果你想要多更高的精度,或者可以指定为run-time或compile-time任意值的精度,那么你需要其他东西.或者:
- 使用arbitrary-precision数字数据类型;这里有一个 list 提供此类类型的库。
- 不是迭代整个数字,而是使用迭代来确定输出中个体 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
,所以你可以坚持使用 float
、double
、long 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);
}
我有一个计算 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 在他的精彩回答中指出的一些不太基本的问题,并专注于我认为是这个问题的核心内容。)
如果您只需要更多的小数位精度,请使用 double
或 long double
而不是 float
。
如果你想要多更高的精度,或者可以指定为run-time或compile-time任意值的精度,那么你需要其他东西.或者:
- 使用arbitrary-precision数字数据类型;这里有一个 list 提供此类类型的库。
- 不是迭代整个数字,而是使用迭代来确定输出中个体 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
,所以你可以坚持使用 float
、double
、long 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);
}