Thread: Getting more digits after dot

  1. #1
    Registered User
    Join Date
    Nov 2017
    Posts
    1

    Question Getting more digits after dot

    Hey, I've been given an assignment to write a code to
    Calculate the constant π value with any accuracy, and i do not know how to get more digits than 15 after the dot. I'm a new guy to programming and was wondering if there was any way to get more digits?
    the code Im working with
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <cmath>
    
    main() {
    
       double n, i;       // Number of iterations and control variable
       double s = 1;      //Signal for the next iteration
       double pi = 0;
    
       printf("Approximation of the number PI through the Leibniz's series\n");
       printf("\nEnter the number of iterations: ");
       scanf("%lf",&n);
       printf("\nPlease wait. Running...\n");
    
       for(i = 1; i <= (n * 2); i += 2){
         pi = pi + s * (4 / i);
         s = -s;
       }
    
       printf("\nAproximated value of PI = %1.16lf\n", pi);
    
    }
    Last edited by Justakas; 11-18-2017 at 03:41 AM.

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Use a larger type such as long double or an arbitrary-precision library such as GMP.
    Devoted my life to programming...

  3. #3
    Registered User
    Join Date
    Jun 2017
    Posts
    88
    GReaper gives the best advice on this, but not the most fun advice I think

    The following is an example of how you can make your own fraction calculations to hundreds of places if you like. If you want to go into the millions or billions, you probably have to ouput it to a file. I think the console window can only hold so much.
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
     
    #define SIZE 500
     
    char* calcFraction(int numer, int denom);
     
    int main() {
    	printf("%s\n", calcFraction(78, 7));
    }
     
    char* calcFraction(int numer, int denom) {
    	static char fraction[SIZE];
    	memset(fraction, 0, SIZE);
    	
    	sprintf(fraction, "%d", numer / denom);
    	strcat(fraction, ".");
     
    	for (int i = strlen(fraction); i < SIZE; ++i) {
    		numer = numer % denom * 10;
    		sprintf(&fraction[i], "%d", numer / denom);
    	}
    	fraction[SIZE - 1] = '\0';
     
    	return fraction;
    }
    Last edited by jack jordan; 11-18-2017 at 12:25 PM.

  4. #4
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Cool trick, I have to say. It provides a false sense of security though, because the produced fractions may be more accurate but it has hard limits on the sizes of the numerator and denominator, which ultimately determine the amount of digits you can influence to produce what you want. What I mean is, for a 32-bit signed integer, maximum value is little over 2 billion, or 2E+9. 1/(2E+9) isn't able to jump over more than 9 digits, therefore it can't produce more than 9 digits for pi.
    Devoted my life to programming...

  5. #5
    Registered User
    Join Date
    Jun 2017
    Posts
    88
    Math programs are difficult for me to put down I guess. I finished a program which can run a Leibniz series far beyond my computer's ability to process it. I had expected better results though. Running 1 million sequence elements only gives me 3.14159
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
     
    #define SIZE 15
    #define SEQUENCE_MAX 2'000'000
     
    char* calcFrac(int numer, const int denom);
    void addToSum(char sum[SIZE], char frac[SIZE]);
    void subFromSum(char sum[SIZE], char frac[SIZE]);
    void prepare(char sum[SIZE], char frac[SIZE]);
    char* leibnizPi();
     
    int main() {
        
        /*
        // for testing functions
        char sum[SIZE] = "0.0";
        sum[SIZE - 1] = '\0';
        */
     
        printf("%s\n", leibnizPi());
    }
     
    char* calcFrac(int numer, const int denom) {
        static char frac[SIZE];
        memset(frac, 0, SIZE);
        
        sprintf(frac, "%d", numer / denom);
        strcat(frac, ".");
     
        for (int i = strlen(frac); i < SIZE - 1; ++i) {
            numer = numer % denom * 10;
            sprintf(&frac[i], "%d", numer / denom);
        }
        if (numer % denom * 10 / denom > 4) {
            ++frac[SIZE - 2];
        }
        frac[SIZE - 1] = '\0';
     
        return frac;
    }
     
    // Add two positive numbers
    void addToSum(char sum[SIZE], char frac[SIZE]) {
     
        prepare(sum, frac);
     
        // add strings
        char addValue[3];
        int carry = 0;
        for (int i = SIZE - 2; i >= 0; --i) {
            if (sum[i] == '.') {
                --i;
            }
            memset(addValue, 0, 3);
            sprintf(addValue, "%d", sum[i] - '0' + frac[i] - '0' + carry);
            if (strtol(addValue, NULL, 0) > 9) {
                carry = 1;
                sum[i] = addValue[1];
            }
            else {
                carry = 0;
                sum[i] = addValue[0];
            }
        }
     
        // final carry
        while (carry == 1) {
            memmove(&sum[1], sum, SIZE - 2);
            ++sum[0];
            carry = 0;
            if (sum[0] - '0' > 9) {
                carry = 1;
                sum[0] -= 10;
            }
        }
    }
     
    // subract positive number (frac) from larger positive number (sum)
    void subFromSum(char sum[SIZE], char frac[SIZE]) {
     
        prepare(sum, frac);
     
        int next = 1;
        for (int i = SIZE - 2; i >= 0; --i) {
            if (sum[i] == '.') {
                --i;
            }
            if (sum[i - 1] == '.') {
                next = 2;
            }
            else {
                next = 1;
            }
     
            // carry
            if (sum[i] < frac[i]) {
                --sum[i - next];
                sum[i] += 10;
            }
     
            sum[i] -= (frac[i] - '0');
        }
        
        // remove front padding
        if (sum[1] == '0') {
            int zero = 0;
            for (int i = 1; sum[i] == '0'; ++i) {
                ++zero;
            }
            zero;
            memmove(sum, &sum[zero], SIZE - zero);
        }
    }
     
    // line up decimal and pad strings
    void prepare(char sum[SIZE], char frac[SIZE]) {
        
        // decimal position
        int sumDec = strcspn(sum, ".");
        int fracDec = strcspn(frac, ".");
        int diff;
     
        // truncate and pad front
        if (sumDec > fracDec) {
            diff = sumDec - fracDec;
            memmove(&frac[diff], frac, SIZE - 1 - diff);
            memset(frac, '0', diff);
            frac[SIZE - 1] = '\0';
        }
        else if (sumDec < fracDec) {
            diff = fracDec - sumDec;
            memmove(&sum[diff], sum, SIZE - 1 - diff);
            memset(sum, '0', diff);
            sum[SIZE - 1] = '\0';
        }
     
        // pad back
        int empty;
        if (strlen(sum) < SIZE) {
            empty = SIZE - strlen(sum) - 1;
            memset(&sum[strlen(sum)], '0', empty);
            frac[SIZE - 1] = '\0';
        }
        if (strlen(frac) < SIZE) {
            empty = SIZE - strlen(frac) - 1;
            memset(&sum[strlen(sum)], '0', empty);
            sum[SIZE - 1] = '\0';
        }
    }
     
    char* leibnizPi() {
        static char sum[SIZE];
        memset(sum, 0, SIZE);
        strcpy(sum, "0.0");
        sum[3] = '\0';
     
        int denom = 1;
        int max = SEQUENCE_MAX;
        while (denom < max) {
            addToSum(sum, calcFrac(4, denom));
            denom += 2;
            subFromSum(sum, calcFrac(4, denom));
            denom += 2;
        }
     
        return sum;
    }
    I wanted to prove GReaper wrong but it looks like I couldn't do it. This is what I am thinking anyway:
    it has hard limits on the sizes of the numerator and denominator
    The numerator and denominator of calcFrac in the decimal portion are what I believe you are referring to. Because this program is designed to find pi, the whole number division is really just a little more flexibility, but not very necessary. The numerator of the decimal portion never needs to be greater than 90, so I don't believe there is a problem with that. If anything int is too large for it. I may not be understanding what you mean though.

  6. #6
    Registered User
    Join Date
    Jun 2017
    Posts
    88
    After thinking about this more, I wanted to correct myself and address the OP's concern more.
    The numerator of the decimal portion never needs to be greater than 90
    Actually, it is the denominator that approaches max int size, but I don't believe it ever becomes a problem.
    Calculate the constant π value with any accuracy, and I do not know how to get more digits than 15 after the dot. I'm a new guy to programming and was wondering if there was any way to get more digits?
    I believe the real limitations are either in code efficiency or the capability of the algorithm rather than the precision of the fractions. I may be wrong, but I don't think the Leibniz series is good enough to be concerned about getting close to pi.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How many digits?
    By JM1082 in forum C++ Programming
    Replies: 4
    Last Post: 06-24-2011, 03:30 PM
  2. Help on sum digits in C
    By KevinH123 in forum C Programming
    Replies: 7
    Last Post: 12-07-2010, 01:36 AM
  3. how to add 2 digits?
    By nefsan in forum C Programming
    Replies: 16
    Last Post: 03-28-2008, 02:41 PM
  4. get all the right digits
    By mag_chan in forum C Programming
    Replies: 6
    Last Post: 11-27-2005, 06:16 AM
  5. Two digits
    By cyberCLoWn in forum C++ Programming
    Replies: 4
    Last Post: 02-23-2004, 01:53 PM

Tags for this Thread