Reputation: 2909
I have a c++ program which calculates Pi but then its value gets cut off after a few decimal places because of the decimal place limit on the float which Pi is stored in.
I've already tried using different data types instead of float but they still have a decimal place limit which is too small.
#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;
}
How do I remove the limit or use a method which stores the value of Pi without it getting cut off after a few decimal places?
Upvotes: 2
Views: 345
Reputation: 131547
(I'm ignoring some of the less fundamental issues which @JAntonioPerez points out in his fine answer and focusing on what I find to be the core of this question.)
If you just need a few more decimal digits of precision, then use double
or long double
instead of float
.
If you want much higher precision, or a precision which can be specified as a run-time or compile-time arbitrary value, then you need something else. Either:
Of course, both options are rather involved and are probably not appropriate for a "toy program" like you seem to be writing.
Upvotes: 2
Reputation: 10740
There are a few big issues here. The first is that you're using std::cout
to print the value, and std::cout
only prints 6 digits by default. The second is that you declared Pi as an int64_t
. That means you'll get at most 1 digit of precision, since Pi is an integer. You need to have it as a floating point type.
So how many digits will you get from each type?
float
double
long double
on clang and gcc, but only 15-16 in Visual Studio__float128
, although that one only works on GCCIf you want more precision than that, you're going to have to use a high-precision arithmetic library that gives you more digits by simulating it. It won't be as fast, but it'll do the job.
You can play around with the amount of precision with each type using this code. I templated calculatePi
on the type, so you can just stick in float
, double
, long double
, or __float128
. It'll print 20 digits. This code should print all 20 digits correctly for __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);
}
Upvotes: 3