Link to home
Start Free TrialLog in
Avatar of cimnik2999
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);
      }
}

Avatar of cimnik2999
cimnik2999

ASKER

damn unicode, okay... quickly to ease things

//        &#8734;
// &#960; =  &#8721;    2(-1)^k x 3^(1/2-k)
//       k=0 -----------------------
//                       2k + 1
//

&#8734 = ifinity
&#960 = pi
&#8721 = sigma/summnation notation
Just keep in mind that rounding error accumulates quickly.

x.mar
Avatar of jkr
Also, you 'minimum delta' seems kinda large. I'd suggest to use

#include <limits>

const double delta = std::numeric_limits<double>::epsilon();
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
Avatar of wayside
wayside

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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