469,271 Members | 997 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,271 developers. It's quick & easy.

how to use PI in c99

i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI

what is the desired way to use the PI constant in a c code then?

#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
....
?

Jul 6 '07 #1
17 11291
Szabolcs Nagy wrote:
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI

what is the desired way to use the PI constant in a c code then?

#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
...
?
The problem with defining PI is that you have at least 3 different
representations of pi: float/double/long double/complex/

What would be the best representation?
And using which rounding mode?

The best thing is to define it yourself and arbitrarily decide that you
want the constant as a (say) long double.
#define PI 3.1415926535897932384626433832795L

jacob
Jul 6 '07 #2
Szabolcs Nagy wrote:
>
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI

what is the desired way to use the PI constant in a c code then?

#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
...
?
In addition to Jacob's points, you should also consider this:

Do you want to define PI as a constant, or as something that
has to be calculated at runtime every time you use it?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Jul 6 '07 #3
Szabolcs Nagy wrote:
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI

what is the desired way to use the PI constant in a c code then?

#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
....
?
There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation of
atan(1) occurs each time PI is used
b) atan() returns a double. Your first form, which has more digits than
most implementations have for a long double, suggests an desire for
a degree of accuracy beyond the requirements even of astrophysics.
If LDBL_DIG DBL_DIG you may well find (4*atan(1)) the less
satisfactory in terms of precision.

Suppose you ran a program like this:

#include <stdio.h>
#include <float.h>
#include <math.h>

#define PI_F 3.1415926535897932384626433832795f
#define PI_D 3.1415926535897932384626433832795
#define PI_L 3.1415926535897932384626433832795l
#define PI_C (4*atan(1))

int main(void)
{
printf("printf PI_x as double:\n");
printf("PI_F %.*g\n", DBL_DIG, PI_F);
printf("PI_D %.*g\n", DBL_DIG, PI_D);
printf("PI_L %.*g\n", DBL_DIG, (double) PI_L);
printf("PI_C %.*g\n\n", DBL_DIG, PI_C);
printf("printf PI_x as long double:\n");
printf("PI_F %.*Lg\n", LDBL_DIG, (long double) PI_F);
printf("PI_D %.*Lg\n", LDBL_DIG, (long double) PI_D);
printf("PI_L %.*Lg\n", LDBL_DIG, PI_L);
printf("PI_C %.*Lg\n\n", LDBL_DIG, (long double) PI_C);

return 0;
}

The output for one implementation
printf PI_x as double:
PI_F 3.14159274101257
PI_D 3.14159265358979
PI_L 3.14159265358979
PI_C 3.14159265358979

printf PI_x as long double:
PI_F 3.14159274101257324
PI_D 3.14159265358979312
PI_L 3.14159265358979324
PI_C 3.14159265358979312
suggests for this implementation:
a) if float operations are faster than doubles, and no more 8
significant digits are needed
#define PI 3.14159265f
suffices
b) if double operations are at least as fast as floats, and no
more than 16 significant digits, or, whatever the relative
speed of floats and doubles, if at 9 but not more than 16
significant digits are needed
#define PI 3.141592653589793
is preferred
c) If the maximum possibel precision is required with a standard
type, use
#define PI 3.1415926535897932384626433832795l
is best.

In fact each of those defines should probably carry all the digits up to
some unneeded level of precision, since a different implementation might
well make use of more than does this implementation.

The only reason I can see for
#define PI (4*atan(1))
is that the implementation may well ensure that this has the maximum
precision and accuracy that a double can attain (but no more).
But that can probably be done with
#define PI 3.1415926535897932384626433832795 /* double */
better.
If you insist on using the (4*atan(1)) form, use, rather than a define,
in each function that now uses the symbol PI
const double PI = 4 * atan(1);
Straining the usual conventions on identifiers that are all caps.
Jul 6 '07 #4
jacob navia <ja***@jacob.remcomp.frwrites:
[...]
The best thing is to define it yourself and arbitrarily decide that you
want the constant as a (say) long double.
#define PI 3.1415926535897932384626433832795L
This has about 102 significant bits of precision; it can silently fail
if long double happens to have a bigger mantissa than that. In most
applications, 32 digits is more than enough, but if it does matter,
it's going to be difficult to track down.

If you really need huge precision, and you need it to adapt to the
precision supported by your implementation, you can use 4*atan(1) --
or, better, 4*atanl(1) -- and arrange your code so it's only evaluated
once.

Or you can define PI as a macro, as above, and fail during compilation
if long double has more precision than you've specified:

#include <float.h>
#define PI 3.1415926535897932384626433832795L
#if LDBL_DIG 32
#error "Definition of PI doesn't use the full precision of long double"
#endif

Or, for most applications, you can just define PI with as many digits
as you're going to need.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 6 '07 #5
On Jul 6, 10:48 am, Martin Ambuhl <mamb...@earthlink.netwrote:
Szabolcs Nagy wrote:
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI
what is the desired way to use the PI constant in a c code then?
#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
....
?

There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation of
atan(1) occurs each time PI is used
Would a conforming program be able to tell if it had been computed at
compile time? I'm not aware of any reason why a good compiler couldn't
do it at compile time.

Jul 6 '07 #6
"J. J. Farrell" <jj*@bcs.org.ukwrites:
On Jul 6, 10:48 am, Martin Ambuhl <mamb...@earthlink.netwrote:
>Szabolcs Nagy wrote:
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI
what is the desired way to use the PI constant in a c code then?
#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
....
?

There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation of
atan(1) occurs each time PI is used

Would a conforming program be able to tell if it had been computed at
compile time? I'm not aware of any reason why a good compiler couldn't
do it at compile time.
No, a conforming program can't tell, as long as the compile-time
computation produces the same result as a run-time computation would
have.

At least one popular C compiler actually does this computation at
compilation time, even without any command-line options to enable
optimization.

This produces some interesting behavior. If the computation is done
at compilation time, the math library is not required. If it needs to
be done at run time, the math library is required, and the program
won't link without an extra option.

<OT>gcc, "-lm"</OT>

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 6 '07 #7
"J. J. Farrell" wrote:
Martin Ambuhl <mamb...@earthlink.netwrote:
.... snip ...
>>
There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation
of atan(1) occurs each time PI is used

Would a conforming program be able to tell if it had been computed
at compile time? I'm not aware of any reason why a good compiler
couldn't do it at compile time.
gcc does.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline dot net
--
Posted via a free Usenet account from http://www.teranews.com

Jul 6 '07 #8
CBFalconer wrote:
"J. J. Farrell" wrote:
>Martin Ambuhl <mamb...@earthlink.netwrote:
... snip ...
>>There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation
of atan(1) occurs each time PI is used
Would a conforming program be able to tell if it had been computed
at compile time? I'm not aware of any reason why a good compiler
couldn't do it at compile time.

gcc does.
And that can be quite WRONG, specially if you want
to redefine atan() to fix a broken implementation
for instance...

I am not sure all this "clever" optimizations are justified
in this case since this constant is known since ages with great
precision.

Why make it simple when you can do it complicated?

That's seems to be the motto here.
Jul 6 '07 #9
jacob navia <ja***@jacob.remcomp.frwrites:
CBFalconer wrote:
>"J. J. Farrell" wrote:
>>Martin Ambuhl <mamb...@earthlink.netwrote:
... snip ...
>>>There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation
of atan(1) occurs each time PI is used
Would a conforming program be able to tell if it had been computed
at compile time? I'm not aware of any reason why a good compiler
couldn't do it at compile time.
gcc does.

And that can be quite WRONG, specially if you want
to redefine atan() to fix a broken implementation
for instance...
All identifiers with file scope in the standard headers, including
atan, are reserved for use as identifiers with external linkage (C99
7.1.3p1). If you define your own atan() function with external
linkage, you're invoking undefined behavior.

The standard reserves certain identifiers for good reasons.
I am not sure all this "clever" optimizations are justified
in this case since this constant is known since ages with great
precision.

Why make it simple when you can do it complicated?

That's seems to be the motto here.
I don't believe that gcc evaluates atan() at compilation time just to
make it easy to define pi. It does so for most or all math functions
(I've run into this for sqrt() as well). It's a perfectly ordinary
optimization.

As a programmer, of course, one probably shouldn't depend on 4*atan(1)
being evaluated at compilation time, since not all compilers will
perform that optimization -- though the penalty for making that
assumption is merely a loss of speed.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 6 '07 #10
jacob navia wrote, On 06/07/07 22:35:
CBFalconer wrote:
>"J. J. Farrell" wrote:
>>Martin Ambuhl <mamb...@earthlink.netwrote:
... snip ...
>>>There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation
of atan(1) occurs each time PI is used
Would a conforming program be able to tell if it had been computed
at compile time? I'm not aware of any reason why a good compiler
couldn't do it at compile time.

gcc does.

And that can be quite WRONG, specially if you want
to redefine atan() to fix a broken implementation
for instance...
Then you can't because the standard does not permit you to redefine
atan. You have to write your own myatan instead, or get a better
implementation.
I am not sure all this "clever" optimizations are justified
in this case since this constant is known since ages with great
precision.
That sounds like an excellent reason *to* optimise it. As the value is
know with great precision why bother recalculating it?
Why make it simple when you can do it complicated?
What is complicated about having a list of functions which, if called
with constants, can be replaced by doing the call at compile time and
inserting the result?
That's seems to be the motto here.
No, the motto is why make the compiled code slow when you can speed it up.

Note that sometimes some of the apparently pointless optimisations (ones
where you would never write code like that) get to speed things up
because of what earlier optimisations have done. Sometimes things like
autoconf can also lead to expressions which might have been variable at
run time ending up as compile time constants.
--
Flash Gordon
Jul 6 '07 #11
On Jul 6, 2:35 pm, jacob navia <j...@jacob.remcomp.frwrote:
CBFalconer wrote:
"J. J. Farrell" wrote:
Martin Ambuhl <mamb...@earthlink.netwrote:
... snip ...
>There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation
of atan(1) occurs each time PI is used
Would a conforming program be able to tell if it had been computed
at compile time? I'm not aware of any reason why a good compiler
couldn't do it at compile time.
gcc does.

And that can be quite WRONG,
How, if the end program can't tell the difference?
specially if you want
to redefine atan() to fix a broken implementation
for instance...
You have to change the implementation to do that, so either apply the
same fix in the compiler bit or disable the optimization.

Jul 7 '07 #12
first thank you all for your answers

Martin Ambuhl wrote:
suggests for this implementation:
a) if float operations are faster than doubles, and no more 8
significant digits are needed
#define PI 3.14159265f
suffices
b) if double operations are at least as fast as floats, and no
more than 16 significant digits, or, whatever the relative
speed of floats and doubles, if at 9 but not more than 16
significant digits are needed
#define PI 3.141592653589793
is preferred
c) If the maximum possibel precision is required with a standard
type, use
#define PI 3.1415926535897932384626433832795l
is best.
let's suppose i use the c) alternative

float f,g;
....
g = f * PI;

will the multiplication be long double or float precision?
i thought the compiler would optimize it and only use floats.
const double PI = 4 * atan(1);
hmm what's the draw back of using
const long double PI = 3.14...L;
instead of
#define PI 3.14...L

Jul 7 '07 #13
On Fri, 06 Jul 2007 13:01:41 -0700, J. J. Farrell wrote:
On Jul 6, 10:48 am, Martin Ambuhl <mamb...@earthlink.netwrote:
>Szabolcs Nagy wrote:
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI
what is the desired way to use the PI constant in a c code then?
#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
....
?

There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation of
atan(1) occurs each time PI is used

Would a conforming program be able to tell if it had been computed at
compile time? I'm not aware of any reason why a good compiler couldn't
do it at compile time.
But the compiler has to pretend that it is done at runtime. For
example, you can't initialize a static variable with it.
--
Army1987
(Replace "NOSPAM" with "email")

Jul 7 '07 #14
Martin Ambuhl wrote:
>
Szabolcs Nagy wrote:
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI

what is the desired way to use the PI constant in a c code then?

#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
....
?

There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation of
atan(1) occurs each time PI is used
b) atan() returns a double. Your first form, which has more digits than
most implementations have for a long double, suggests an desire for
a degree of accuracy beyond the requirements even of astrophysics.
If LDBL_DIG DBL_DIG you may well find (4*atan(1)) the less
satisfactory in terms of precision.

Suppose you ran a program like this:

#include <stdio.h>
#include <float.h>
#include <math.h>

#define PI_F 3.1415926535897932384626433832795f
#define PI_D 3.1415926535897932384626433832795
#define PI_L 3.1415926535897932384626433832795l
#define PI_C (4*atan(1))

int main(void)
{
printf("printf PI_x as double:\n");
printf("PI_F %.*g\n", DBL_DIG, PI_F);
printf("PI_D %.*g\n", DBL_DIG, PI_D);
printf("PI_L %.*g\n", DBL_DIG, (double) PI_L);
printf("PI_C %.*g\n\n", DBL_DIG, PI_C);

printf("printf PI_x as long double:\n");
printf("PI_F %.*Lg\n", LDBL_DIG, (long double) PI_F);
printf("PI_D %.*Lg\n", LDBL_DIG, (long double) PI_D);
printf("PI_L %.*Lg\n", LDBL_DIG, PI_L);
printf("PI_C %.*Lg\n\n", LDBL_DIG, (long double) PI_C);

return 0;
}

The output for one implementation
printf PI_x as double:
PI_F 3.14159274101257
PI_D 3.14159265358979
PI_L 3.14159265358979
PI_C 3.14159265358979

printf PI_x as long double:
PI_F 3.14159274101257324
PI_D 3.14159265358979312
PI_L 3.14159265358979324
PI_C 3.14159265358979312

suggests for this implementation:
a) if float operations are faster than doubles, and no more 8
significant digits are needed
#define PI 3.14159265f
suffices
b) if double operations are at least as fast as floats, and no
more than 16 significant digits, or, whatever the relative
speed of floats and doubles, if at 9 but not more than 16
significant digits are needed
#define PI 3.141592653589793
is preferred
c) If the maximum possibel precision is required with a standard
type, use
#define PI 3.1415926535897932384626433832795l
is best.
Pi can be calculated for any standard type.

/* BEGIN new.c */

#include <stdio.h>
#include <float.h>

long double fs_pil(void)
{
long unsigned n;
long double a, b;
static long double p;
static int initialized;

if (!initialized) {
initialized = 1;
n = 1;
a = 3;
do {
a /= 9;
b = a / n;
n += 2;
a /= 9;
b -= a / n;
n += 2;
p += b;
} while (b LDBL_EPSILON / 4);
n = 1;
a = 2;
do {
a /= 4;
b = a / n;
n += 2;
a /= 4;
b -= a / n;
n += 2;
p += b;
} while (b LDBL_EPSILON / 2);
p *= 4;
}
return p;
}

int main(void)
{
printf("fs_pil() - 3.1415926535897932384626433832795L is %Le\n",
fs_pil() - 3.1415926535897932384626433832795L);
return 0;
}

/* END new.c */

--
pete
Jul 7 '07 #15
On Sat, 07 Jul 2007 08:17:36 -0000, Szabolcs Nagy
<ns*******@gmail.comwrote:
>first thank you all for your answers

Martin Ambuhl wrote:
>suggests for this implementation:
a) if float operations are faster than doubles, and no more 8
significant digits are needed
#define PI 3.14159265f
suffices
b) if double operations are at least as fast as floats, and no
more than 16 significant digits, or, whatever the relative
speed of floats and doubles, if at 9 but not more than 16
significant digits are needed
#define PI 3.141592653589793
is preferred
c) If the maximum possibel precision is required with a standard
type, use
#define PI 3.1415926535897932384626433832795l
is best.
let's suppose i use the c) alternative

float f,g;
...
g = f * PI;

will the multiplication be long double or float precision?
i thought the compiler would optimize it and only use floats.
Assuming you assign a value to f, it will be converted to long double,
the multiplication will be performed, and the result will be converted
to float. Look up arithmetic promotions in your reference of choice.
>
> const double PI = 4 * atan(1);
hmm what's the draw back of using
const long double PI = 3.14...L;
instead of
#define PI 3.14...L
1. You could not use PI where a compile time constant would be
needed.

2. Certain calculations would be deferred until execution time. For
example, in the statement
c = 2 * PI * r;
with the #define, the compiler could computer 2 * PI and use that
value in the generated code which would involve only one multiply
during program execution. With the const, I think most compilers will
generate two multiplies in the executable code.

3. Unless you define PI at file scope, it will only be visible in the
block it is defined in. The #define is "visible" for the rest of the
translation unit and, if you put it in a header, for as many units as
you want.

On the other hand, with the const, your debugger would show you the
variable PI just like it does any other.
Remove del for email
Jul 7 '07 #16
Army1987 wrote:
On Fri, 06 Jul 2007 13:01:41 -0700, J. J. Farrell wrote:
On Jul 6, 10:48 am, Martin Ambuhl <mamb...@earthlink.netwrote:
Szabolcs Nagy wrote:
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI

what is the desired way to use the PI constant in a c code then?

#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
....
?

There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation of
atan(1) occurs each time PI is used
Would a conforming program be able to tell if it had been computed at
compile time? I'm not aware of any reason why a good compiler couldn't
do it at compile time.

But the compiler has to pretend that it is done at runtime. For
example, you can't initialize a static variable with it.
Yes. That's why gcc emits a diagnostic when compiling such a construct
under conforming mode.

Jul 7 '07 #17
On Jul 7, 1:43 am, Army1987 <army1...@NOSPAM.itwrote:
On Fri, 06 Jul 2007 13:01:41 -0700, J. J. Farrell wrote:
On Jul 6, 10:48 am, Martin Ambuhl <mamb...@earthlink.netwrote:
Szabolcs Nagy wrote:
i've just found out (searching through n1124.pdf) that in c99 math.h
does not contain M_PI
what is the desired way to use the PI constant in a c code then?
#define PI 3.1415926535897932384626433832795
#define PI (4*atan(1))
....
?
There are two obvious disadvantages to the (4*atan(1)) form
a) atan(1) is not computed at compile time, so the computation of
atan(1) occurs each time PI is used
Would a conforming program be able to tell if it had been computed at
compile time? I'm not aware of any reason why a good compiler couldn't
do it at compile time.

But the compiler has to pretend that it is done at runtime. For
example, you can't initialize a static variable with it.
Obviously; if the C code contains a call to atan(1) the compiler has
to behave in the way prescribed by the C standard for when the code
contains a call to atan(1). How the compiler actually implements that
call is its business.

Jul 8 '07 #18

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by William C. White | last post: by
2 posts views Thread by Albert Ahtenberg | last post: by
3 posts views Thread by James | last post: by
reply views Thread by Ollivier Robert | last post: by
1 post views Thread by Richard Galli | last post: by
4 posts views Thread by Albert Ahtenberg | last post: by
1 post views Thread by inderjit S Gabrie | last post: by
2 posts views Thread by Jack | last post: by
3 posts views Thread by Sandwick | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.