definitions of constants such as pi and e

M

Matt

Does the language have header files containing definitions of numbers
such as pi and e?

I believe some implementations used to have those, but I can't find them
in Stroustrup.

Thanks.
 
B

benben

Matt said:
Does the language have header files containing definitions of numbers
such as pi and e?

I believe some implementations used to have those, but I can't find them
in Stroustrup.

Thanks.

If you couldn't find any, just google for the value and copy.

Ben
 
A

andy

Matt said:
Does the language have header files containing definitions of numbers
such as pi and e?

I believe some implementations used to have those, but I can't find them
in Stroustrup.

Thanks.

FWIW...

There is a history to trying to solve constants problem in an elegant
way with various solutions having being proposed and rejected on
gmane.comp.lib.boost.devel newsgroup.

The solutions fell into 4 areas IIRC:

solution1: Use a variable e.g

//some math header

extern const double pi;

Note that one shouldnt define it in the header due to the ODR rule so
it would require linking a library in the application or defining in a
source file, which was felt to be inconvenient. The other drawback was
that it cant simultaneously be float, double and long double so it will
never be right for everybody.

solution 2: use a function e.g

inline double pi()
{
return 3.141592653589793238462643383279502884197;
}

This suffers in that you cant control the floating point type and it
seems that people hate the function notation to call it. You could make
it a template of course, but you would have to provide the template
parameter when invoked.

solution 3: Use a smart object

struct pi{
template <typename T>
T pi_function(); // get pi as a T
template <typename T>
operator T() { return pi_function<T>();}
}


This may or may not be how it went. Whatever... The problem this had
was deducing the type to convert to in some situations IIRC.

solution 4: My preferred solution and the one I use, but suffers from
various of the problems above

template <typename T>
struct constant_{

static const T pi;
static const T e;
};

// convenient version for My Favourite float
#ifndef MY_FAVOURITE_FLOAT
#define MY_FAVOURITE_FLOAT double
#endif
struct constant : constant_<MY_FAVOURITE_FLOAT>{};

int main()
{
float val1 = constant_<float>::pi;
double val = constant::pi;
}

Of course this requires a library or source and visible use of
templates in the first invocation at least.


Finally there is an M_PI macro available in some versions of <cmath>
normally via its nested include <math.h>, but that is horrible...

So If anyone has any ideas .... ???

regards
Andy Little
 
W

Walter Bright

Matt said:
Does the language have header files containing definitions of numbers
such as pi and e?

I believe some implementations used to have those, but I can't find them
in Stroustrup.

Here are the ones used in D's std.math, good to 80 bits:

const real E = 2.7182818284590452354L;
const real LOG2T = 0x1.a934f0979a3715fcp+1;
const real LOG2E = 0x1.71547652b82fe178p+0;
const real LOG2 = 0x1.34413509f79fef32p-2;
const real LOG10E = 0.43429448190325182765;
const real LN2 = 0x1.62e42fefa39ef358p-1;
const real LN10 = 2.30258509299404568402;
const real PI = 0x1.921fb54442d1846ap+1;
const real PI_2 = 1.57079632679489661923;
const real PI_4 = 0.78539816339744830962;
const real M_1_PI = 0.31830988618379067154;
const real M_2_PI = 0.63661977236758134308;
const real M_2_SQRTPI = 1.12837916709551257390;
const real SQRT2 = 1.41421356237309504880;
const real SQRT1_2 = 0.70710678118654752440;

The hex float notation is C99 compatible. I prefer hex float for
constants, as it ensures accuracy to the last bit without worrying about
decimal conversion roundoff errors.

-Walter Bright
www.digitalmars.com C, C++, D programming language compilers
 
A

andy

Walter said:
Here are the ones used in D's std.math, good to 80 bits:

[...]

Of course C++ has a selection of floating point types, each with
implementation defined behaviour... a clear **win** [note1] over the
single 'real' type in D

[note1]
meant with a hint of sarcasm...;-)

regards
Andy Little
 
O

osmium

Matt said:
Does the language have header files containing definitions of numbers such
as pi and e?

No, the standard language does not. One common addition to some compilers
is to put them in <math.h> as macros with names such as M_PI.
 
P

P.J. Plauger

... ha ha very practical ...

Ha ha. Look what I found:

http://pi.lacim.uqam.ca/eng/table_en.html

BTW, when you put such constants in your program:

1) Keep 35 significant digits. This guarantees good results for 113-bit
(16-byte) long double, which needs 33+ digits, but avoids the common
compiler bug that causes overflow while the constant is being formed,
which occurs around 38 digits.

2) Always append F for float or L for long double.

3) Don't bother with C99-style hexadecimal, the decimal form is going
to be accurate enough for your needs.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
R

red floyd

osmium said:
No, the standard language does not. One common addition to some compilers
is to put them in <math.h> as macros with names such as M_PI.

#include <cmath>

const double e = std::exp(1.0);
const double pi = std::atan(1.0) * 4.0;
 
W

Walter Bright

P.J. Plauger said:
Ha ha. Look what I found:

http://pi.lacim.uqam.ca/eng/table_en.html

BTW, when you put such constants in your program:

1) Keep 35 significant digits. This guarantees good results for 113-bit
(16-byte) long double, which needs 33+ digits, but avoids the common
compiler bug that causes overflow while the constant is being formed,
which occurs around 38 digits.

2) Always append F for float or L for long double.

3) Don't bother with C99-style hexadecimal, the decimal form is going
to be accurate enough for your needs.

Since we never know what someone else's needs are, it's best to provide
the constants accurate to the last bit. The reason to use C99 hex floats
is to avoid things like "the common compiler bug" that goof up the
conversion from decimal to float. Another problem with some conversion
algorithms is that some bit patterns cannot be arrived at by
manipulating the decimal value - it may 'skip' over the last bit. With
hex floats you can just set the right bit pattern, without wasting time
twiddling with various decimal values trying to asymptotically approach
it. Even worse, installing a compiler update might slightly change the
compiler's algorithm, meaning you have to start over (if you even notice
it's gone awry). One particularly fun game of brinksmanship is to get
LDBL_MAX without falling over into infinity. It's easy with hex floats:

#define LDBL_MAX 0x1.FFFFFFFFFFFFFFFEp+16383L

It's too bad it's hard to find reliable references to bit patterns for
the constants. The ones I use are from Hart & Cheney's "Computer
Approximations."

Many compilers still inexplicably don't support hex floats, for those
I've seen people (i.e. Stephen Moshier in his most excellent Cephes math
library) forced to resort to reinterpret casting of tuples of longs.

(An awfully common problem is one you referenced above - failing to
append an 'L'. The symptoms can be very subtle. It's one I've fallen
victim to enough times that D will internally will treat constants to
the full 80 bit precision, even if they are typed as doubles. The only
time they get rounded to 64 bits is when they are actually assigned to a
double.)

-Walter Bright
www.digitalmars.com C, C++, D programming languages
 
M

Matt

red said:
#include <cmath>

const double e = std::exp(1.0);
const double pi = std::atan(1.0) * 4.0;

That seems good, assuming the compiler would optimize away the function
calls.

Still I guess you would have a problem if you were to assign to a float.
So you need definitions that use expf and atanf too.
 
M

Matt

red said:
#include <cmath>

const double e = std::exp(1.0);
const double pi = std::atan(1.0) * 4.0;

Please disregard my preceding remark about the compiler optimizing away
the function call.
 
M

Matt

P.J. Plauger said:
Ha ha. Look what I found:

http://pi.lacim.uqam.ca/eng/table_en.html

BTW, when you put such constants in your program:

1) Keep 35 significant digits. This guarantees good results for 113-bit
(16-byte) long double, which needs 33+ digits, but avoids the common
compiler bug that causes overflow while the constant is being formed,
which occurs around 38 digits.

2) Always append F for float or L for long double.

3) Don't bother with C99-style hexadecimal, the decimal form is going
to be accurate enough for your needs.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

I wonder whether supplying a literal has any advantages over
initializing a constant to say 4*atan(1) for pi.
 
R

red floyd

Matt said:
That seems good, assuming the compiler would optimize away the function
calls.

Still I guess you would have a problem if you were to assign to a float.
So you need definitions that use expf and atanf too.

Why?

Double converts to float easily.

float f = static_cast<float>(e);
float p = static_cast<float>(pi);
 
W

Walter Bright

Matt said:
I wonder whether supplying a literal has any advantages over
initializing a constant to say 4*atan(1) for pi.

1) It doesn't need code to initialize it at run time.
2) It's probably more accurate.
 
O

osmium

P.J. Plauger said:
It's more likely to be correct.

But the more likely reason it is used is someone simply showing off his
erudition. Anyone who knows this bit of lore also has a perfectly good
value for pi available to him somewhere in his archives or by making a few
key strokes.
 
M

Matt

osmium said:
:




But the more likely reason it is used is someone simply showing off his
erudition. Anyone who knows this bit of lore also has a perfectly good
value for pi available to him somewhere in his archives or by making a few
key strokes.

Which bit of lore?
 
N

noone

Not unlike using words like "erudition", right? ;^)

Assuming you know what you're doing, basing constants on some identity
rule makes more sense to me since too often typing in a long literal value
will suffer from mistakes of transposed or dropped digits. Of course the
down side is that the formula you use to compute the constant should
have enough precision (and accuracy) to be useful. and let us not forget
that if misused, basing a constant on the calculation of some identity can
lead to inefficient code, such as recomputing the identity over and over
again in a loop (ignoring the forthcoming compiler optimizer arguments
that I know the preceding comment will generate). :^)

It is late. I need beer and tobacco.

-noone of consequence
 
L

Liang Zhang

And this kind of definition of pi ( call funcition atan()) will cause
performance issues, I think there is no good to apply this way otherwise
defining pi as 3.14159 directly

--

Best Regards

Liang Zhang

Developer
SAP Labs China

T: +86 21 61006699-7775
F: +86 21 65984520
Email (e-mail address removed)

SAP LABS CHINA : INNOVATE THE FUTURE
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,438
Messages
2,571,699
Members
48,796
Latest member
Greg L.
Top