java.lang.Math.PI是否等于GCC的M_PI? [英] Is java.lang.Math.PI equal to GCC's M_PI?

查看:260
本文介绍了java.lang.Math.PI是否等于GCC的M_PI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Java和C / C ++中都编写了几个参考算法。其中一些算法使用&pi ;.我希望每个算法的两个实现产生相同的结果,而不是四舍五入。到目前为止一直工作的一种方法是使用一个自定义的 pi 常量,这在两种语言中都是一样的,例如3.14159。然而,当在Java和GCC库中已经定义了高精度的常量时,定义pi是很愚蠢的。



我花了一些时间编写快速测试程序,查看每个库的文档,并阅读浮点类型。但是我还没能说服自己java.lang.Math.PI(或java.lang.StrictMath.PI)在math.h中是否等于M_PI。

GCC 3.4.4(cygwin)math.h包含:

  #define M_PI 3.14159265358979323846 
^^^^^

但是这个

  printf(%。20f,M_PI); 

产生

  3.14159265358979311600 
^^^^^

这表明最后5位数不可信。



同时,Javadocs说java.lang.Math.PI是:


double 的值比
更接近于 pi
的周长

  public static final double PI 3.141592653589793d 

它省略了最后一个问题从常量中取5个数字。

  System.out.printf(%。20f\\\
,Math.PI);

产生

  3.14159265358979300000 
^^^^^

如果您在浮动点数据类型,你能说服我这些库常量是完全相等的?或者说他们肯定是不平等的?他们是平等的,使用他们将保证GCC和Java的实现相同的算法是在同一个基础上 - ndash;至少与使用手工定义的 pi 常数



一个警告,由 S暗示。 Lott ,GCC实现必须在 double 数据类型中保存 M_PI ,而不是 long double ,以确保等价。 Java和GCC对于它们各自的 double 数据类型似乎都使用IEEE-754的64位十进制表示。可以如下获得库值的字节表示(MSB到LSB),表示为 double ,如下所示(感谢
pi_bytes.c:

<$ p

$ p> #include< math.h>
#include< stdio.h>
int main()
{
double pi = M_PI;
printf(%016llx \\\
,*((uint64_t *)& pi));

pi_bytes.java:

  class pi_bytes 
{
public static void main(String [] a)
{
System.out.printf( 016x \ n,Double.doubleToRawLongBits(Math.PI));




同时运行:

  $ gcc -lm -o pi_bytes pi_bytes.c&& ./pi_bytes 
400921fb54442d18

$ javac pi_bytes.java&& java pi_bytes
400921fb54442d18

M_PI (作为 double )和 Math.PI 是相同的,直到它们的位。 >

† &ndash的;正如 Steve Schnepp 所指出的那样,sin,cos,exp等数学函数的输出不能保证是即使这些计算的输入是按位相同的。

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?

解决方案

Yes, they are equal, and using them will insure that GCC and Java implementations of the same algorithm are on the same footing – at least as much as using a hand-defined pi constant would.

One caveat, hinted by S. Lott, is that the GCC implementation must hold M_PI in a double data type, and not long double, to ensure equivalence. Both Java and GCC appear to use IEEE-754's 64-bit decimal representation for their respective double data types. The bytewise representation (MSB to LSB) of the library value, expressed as a double, can be obtained as follows (thanks to JeeBee):

pi_bytes.c:

#include <math.h>
#include <stdio.h>
int main()
{
   double pi = M_PI;
   printf("%016llx\n", *((uint64_t*)&pi));
}

pi_bytes.java:

class pi_bytes
{
   public static void main(String[] a)
   {
      System.out.printf("%016x\n", Double.doubleToRawLongBits( Math.PI ) );
   }
}

Running both:

$ gcc -lm -o pi_bytes pi_bytes.c && ./pi_bytes
400921fb54442d18

$ javac pi_bytes.java && java pi_bytes
400921fb54442d18

The underlying representations of M_PI (as a double) and Math.PI are identical, down to their bits.

† – As noted by Steve Schnepp, the output of math functions such as sin, cos, exp, etc. is not guaranteed to be identical, even if the inputs to those computations are bitwise identical.

这篇关于java.lang.Math.PI是否等于GCC的M_PI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆