cimnik2999
asked on
calcualting digits of pi
lately, gaining intest in pi from some insight from a friend, i wrote this function to fill and array with digits of pi. it seems, however to work only for the first 17 digits of pi, yet my mathematical reasoning seems sound.
since pi is equal to:
∞
π = ∑ 2(-1)^k x 3^(1/2-k)
k=0 -----------------------
2k + 1
what i decided to do is to evaulate each term. one i found that the one's column was no longer affected, that i could round off the deciamals, so for the first case, get 3, subtract that from the current obtained value of pi, then multiply this value by 10 and any other caluclated terms now by 10... one i find that the ones now is no longer affected, i do that same thing over again... extract the 1, multiply pi by 10, and any other terms now by 100.
However... this system only works for calculating the first 17 or so digits of pi. what am i doing wrong? here is the code to aid u helping me ;)
CODE---------------------- ---------- ---------- ---------- ---------- ---------- ---------- --
// Evaluates the numerator for the calc_pi function; SEE BELOW
inline double numerator_pow(int k, int i)
{
double value = 2 * pow(3.0, (0.5 - double(k))) * pow(10.0, i);
return (k % 2 == 1) ? -1 * value : value;
}
// Fills an array with the various digits of pi
// ∞
// π = ∑ 2(-1)^k x 3^(1/2-k)
// k=0 -----------------------
// 2k + 1
//
// NOTE: Floating point impression prevents this line:
// double value = numerator(++k) / (2*k + 1) * pow(10.0, i);
// from producing a value greater than zero after the first 15 digits
void pi_digits(char* digits, int length)
{
int k = 0; // Term counter for the sumnation
double pi = 2 * sqrt(3.0); // Calculate the first term in the expansion
const double delta = 0.0000001; // Calculate a limiter value of the set precision
const double neg_delta = -1 * delta; // Negative limiter. Half the term are negative so lowers
// the number of operations if its calculated before
for(int i = 0; i < length; ++i)
{
do
{
double value = (numerator_pow(++k, i)) / (2*k + 1);
cout << i << " " << value << endl;
if(((k % 2 == 1) ? neg_delta : value) > ((k % 2 == 1) ? value : delta))
pi += value;
else
{
int digit = (int)pi;
double temp = (pi + value) * 10;
pi = temp - (digit * 10);
digits[i] = digit;
break;
}
} while(true);
}
}
since pi is equal to:
∞
π = ∑ 2(-1)^k x 3^(1/2-k)
k=0 -----------------------
2k + 1
what i decided to do is to evaulate each term. one i found that the one's column was no longer affected, that i could round off the deciamals, so for the first case, get 3, subtract that from the current obtained value of pi, then multiply this value by 10 and any other caluclated terms now by 10... one i find that the ones now is no longer affected, i do that same thing over again... extract the 1, multiply pi by 10, and any other terms now by 100.
However... this system only works for calculating the first 17 or so digits of pi. what am i doing wrong? here is the code to aid u helping me ;)
CODE----------------------
// Evaluates the numerator for the calc_pi function; SEE BELOW
inline double numerator_pow(int k, int i)
{
double value = 2 * pow(3.0, (0.5 - double(k))) * pow(10.0, i);
return (k % 2 == 1) ? -1 * value : value;
}
// Fills an array with the various digits of pi
// ∞
// π = ∑ 2(-1)^k x 3^(1/2-k)
// k=0 -----------------------
// 2k + 1
//
// NOTE: Floating point impression prevents this line:
// double value = numerator(++k) / (2*k + 1) * pow(10.0, i);
// from producing a value greater than zero after the first 15 digits
void pi_digits(char* digits, int length)
{
int k = 0; // Term counter for the sumnation
double pi = 2 * sqrt(3.0); // Calculate the first term in the expansion
const double delta = 0.0000001; // Calculate a limiter value of the set precision
const double neg_delta = -1 * delta; // Negative limiter. Half the term are negative so lowers
// the number of operations if its calculated before
for(int i = 0; i < length; ++i)
{
do
{
double value = (numerator_pow(++k, i)) / (2*k + 1);
cout << i << " " << value << endl;
if(((k % 2 == 1) ? neg_delta : value) > ((k % 2 == 1) ? value : delta))
pi += value;
else
{
int digit = (int)pi;
double temp = (pi + value) * 10;
pi = temp - (digit * 10);
digits[i] = digit;
break;
}
} while(true);
}
}
Just keep in mind that rounding error accumulates quickly.
x.mar
x.mar
Also, you 'minimum delta' seems kinda large. I'd suggest to use
#include <limits>
const double delta = std::numeric_limits<double >::epsilon ();
#include <limits>
const double delta = std::numeric_limits<double
ASKER
well... if i made it smaller, such as 0.1, i would then only get 15 digits, instead of 17... what is the value of std::numeric_limits<double >::epslon( ) anyways?
That depends on your machine - it is the maximum accuracy or the minimal difference between floating point numbers that your processor can handle.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
yeah i figured it might be a precision error, and thats why i made sure that the current digit would be above the decimal, in an attempt to get around this impressions... would that not get around it? ill look into an arbitrary precision library
ASKER
// ∞
// π = ∑ 2(-1)^k x 3^(1/2-k)
// k=0 -----------------------
// 2k + 1
//
∞ = ifinity
π = pi
∑ = sigma/summnation notation