I am coding several reference algorithms in both Java and C/C++. Some of these algorithms use π. I would like for the two implementations of each algorithm to produce identical results, without rounding differently. One way to do this that has worked consistently so far is to use a custom-defined pi
constant which is exactly the same in both languages, such as 3.14159. However, it strikes me as silly to define pi when there are already high-precision constants defined in both the Java and GCC libraries.
I've spent some time writing quick test programs, looking at documentation for each library, and reading up on floating-point types. But I haven't been able to convince myself that java.lang.Math.PI (or java.lang.StrictMath.PI) is, or is not, equal to M_PI in math.h.
GCC 3.4.4 (cygwin) math.h contains:
#define M_PI 3.14159265358979323846
^^^^^
but this
printf("%.20f", M_PI);
produces
3.14159265358979311600
^^^^^
which suggests that the last 5 digits cannot be trusted.
Meanwhile, Javadocs say that java.lang.Math.PI is:
The
double
value that is closer than any other to pi, the ratio of the circumference of a circle to its diameter.
and
public static final double PI 3.141592653589793d
which omits the questionable last five digits from the constant.
System.out.printf("%.20f\n", Math.PI);
produces
3.14159265358979300000
^^^^^
If you have some expertise in floating-point data types, can you convince me that these library constants are exactly equal? Or that they are definitely not equal?
Note the following.
The two numbers are the same to 16 decimal places. That's almost 48 bits which are the same.
In an IEEE 64-bit floating-point number, that's all the bits there are that aren't signs or exponents.
The #define M_PI
has 21 digits; that's about 63 bits of precision, which is good for an IEEE 80-bit floating-point value.
What I think you're seeing is ordinary truncation of the bits in the M_PI
value.
What you want to do is print out the raw bit pattern for the PI values and compare them.
In Java use the http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Double.html#doubleToRawLongBits(double) method to get the long value that you should print as binary.
Java 5 gives:
In C, you can do double pi = M_PI; printf("%lld\n", pi);
to obtain the same 64bit integer: 4614256656552045848 (thanks Bruno).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With