Search code examples
cpi

Value of PI in C


How should one define the value of PI? What are the effects of using the various PI definitions? Would declaring the variables as a long double suffice for PI_b, float for PI and PI_a? Could there be a change in the results depending on the defination one is using in a program?

Thank you.

#ifdef M_PI
#define PI M_PI
#else
#define PI 3.14159265358979323846264338327950288420   
#endif

//OR 

#define PI_a 3.14159265358979323846 

//OR

#define PI_b 3.14159265358979323846264338327950288420  /* 3 more than LDBL_DECIMAL_DIG */


Solution

  • How should one define the value of PI?

    It depends on your objectives.

    Could there be a change in the results depending on the defination one is using in a program?

    In general, absolutely. How likely that is depends on details of your C implementation's floating-point types, the specific forms of the constants you use, the nature and details of the calculation, and how precisely you express the results.

    With your specific examples, it's unlikely. Read on for details.

    What are the effects of using the various PI definitions? Would declaring the variables as a long double suffice for PI_b, float for PI and PI_a?

    In the first place, there is rarely a good reason to use float, other than for minimizing storage size. Modern CPUs suffer no performance penalty from using doubles -- in fact, computing with doubles may be marginally faster than computing with floats.

    In the second place, the types of variables to which you assign floating constants is not the only relevant consideration.

    Since you raise the questions of data type and variation in results and give estimates of Pi to large numbers of decimal digits, I infer that you are looking for the most precise estimates of Pi supported by the various available floating-point data types, and how to use them in your programs.

    In that case, it is important to understand that numeric constants are assigned data types based on their lexical form, and that determines their precision. No matter how many digits you provide, a decimal floating-point constant has type double if it is without any suffix, type float if it is suffixed with f or F, or type long double if it is suffixed with l or L. The precision of the result is limited by the data type, no matter how many digits you write.

    In particular, your numeric definitions of PI, PI_a, and PI_b macros all expand to floating constants of type double. They all have more than enough significant decimal digits to fully determine all the bits of a double of a typical C implementation, and the leading digits are the same, so in such an implementation they all express the same double value. You can assign that value to a variable of type long double, but that will not automagically convert it to a higher-precision estimate.

    If you want a floating constant expressing a higher precision estimate of Pi than a double can accommodate then you need to use a long double constant. For example,

    // Note the 'L' suffix making this a long double constant:
    #define PI_l 3.14159265358979323846264338327950288420L
    

    Do note, however, that whether long double actually does provide more precision than does double is implementation dependent, and even among those that do, not all long doubles you might meet are precise to the 38 decimal digits of your constant.

    Consider this program:

    #include <stdio.h>
    
    #define PI_l 3.14159265358979323846264338327950288420L
    
    int main(void) {
        // The type casts produce effects equivalent to assigning to a
        // variable of the specified type and then reading back its value:
        printf("As float:       %.24f\n", (float) PI_l);
        printf("As double:      %.24f\n", (double) PI_l);
        printf("As long double: %.24Lf\n", PI_l);
    }
    

    For me, its output is

    As float:       3.141592741012573242187500
    As double:      3.141592653589793115997963
    As long double: 3.141592653589793238512809
    

    Note well that the three are all different from each other, and that even the long double version diverges at the 20th digit from the expression of the constant in the source code.