gamma(double x)的定义是什么?为什么它在两个gcc版本上有所不同?

时间:2013-08-08 01:11:34

标签: gcc math.h cmath

在不幸的情况下,我发现我的标准库实现<math.h><cmath>(C ++)显然包含一个函数的定义,其原型如下:

double gamma(double x);

虽然我没有看到它在语言标准中的任何地方列出(我可以访问的草稿)。

在Mac OS X上使用gcc v4.2.1,该功能的评估与tgamma相同,实际上是标准中给出的名称。 (reference)

但是在Ubuntu 12.04上的gcc v4.6.3上,该函数评估的是不同的东西。

我不明白为什么名为gamma的函数会编译,但为什么编译器之间的结果不一样?

这是一个简单的测试程序:

#include<iostream>
#include<sstream>
#include<math.h> // or <cmath>

int main(int argc, char **argv)
{
    std::stringstream conversionStream(argv[1]);
    double input;
    conversionStream >> input;
    std::cout << "gamma( " << input << " ) = " << gamma(input) << std::endl;
    return 0;
}

使用1个参数编译并运行:

$ g++ -o gamma_test gamma_test.cpp 
$ ./gamma_test 1.0
gamma( 1 ) = 1

但是Ubuntu gcc v4.6.3的输出是0!

2 个答案:

答案 0 :(得分:4)

总结:历史上的困惑比比皆是;避免gamma()并使用tgamma()

实现这些功能的是数学库,而不是gcc(编译器)。如果你在MacOS和Ubuntu上看到不同的行为,可能是因为Ubuntu使用glibc而MacOS使用其他东西。

ISO C标准库中没有名为gamma的函数。

有一些名为lgammatgamma的标准函数。引用N1570(2011 ISO C标准的最新草案)第17.12.8.3和17.12.8.4节:

  

#include <math.h>
  double lgamma(double x);
  float lgammaf(float x);
  long double lgammal(long double x);

     

lgamma 函数计算绝对值的自然对数    x 的gamma值。如果 x 太大,则会出现范围错误。一根杆子   如果 x 是负整数或零,则可能会出错。

     

#include <math.h>
  double tgamma(double x);
  float tgammaf(float x);
  long double tgammal(long double x);

     

tgamma 函数计算 x 的gamma函数。域错误   如果 x 是负整数或零,则可能出现极点错误。范围   如果 x 的幅度太大,则会发生错误,如果出现错误,则可能会发生错误    x 的幅度太小。

这些功能未出现在1990 ISO C标准中。它们是由C99引入的。

引用Linux man page for gamma

  

不推荐使用这些功能:而是使用 tgamma (3)或    lgamma (3)功能,视情况而定。

     

有关Gamma功能的定义,请参阅 tgamma (3)。

  • * BSD版本

      

    4.4BSD中的libm和某些版本的FreeBSD有一个 gamma ()函数,可以像人们期望的那样计算Gamma函数。

  • glibc版

      

    Glibc具有 gamma ()函数,相当于 lgamma (3)并计算Gamma函数的自然对数。

和历史记录:

  

4.2BSD有 gamma ()计算ln(| Gamma(| x |)|),留下符号   外部整数signgam中的Gamma(| x |)。在4.3BSD中的名称   被改为 lgamma (3),并且手册页承诺

     

“在未来的某个时间,名称伽马将被修复并且   用于Gamma函数“

     

这确实发生在4.4BSD中,其中 gamma ()计算Gamma   功能(对signgam没有影响)。但是,这来得太晚了,   我们现在有 tgamma (3),“真正的伽玛”功能。

由于gamma不是标准C函数,因此使用gcc -std=c99 -pedanticgcc -std=c11 -pedantic进行编译时,至少应对任何尝试调用它的方式发出警告。

如果你想要自然对数,你应该使用tgamma()(或lgamma())并避免使用gamma()

C标准似乎没有说出Gamma功能是什么。 Linux tgamma() man page会这样做(但如果您尝试使用它,您可能已经知道它是什么):

  

Gamma功能由

定义      

Gamma(x)=从0到无穷大的积分t ^(x-1)e ^ -t dt

     

除了非正整数之外,它是为每个实数定义的   对于非负整数m,有一个

     

Gamma(m + 1)= m!

     

,更一般地说,对于所有x:

     

Gamma(x + 1)= x * Gamma(x)

     

此外,以下内容对于x之外的所有x值都有效   极:

     

伽马(x)*伽马(1 - x)= PI / sin(PI * x)

答案 1 :(得分:3)

在某些平台上(linux和bsd pre-4.2左右),gammalgamma(gamma函数的日志)。在其他平台上(osx和bsd post-4.4ish),它是tgamma(“真正的”伽玛函数)。这是一种历史的好奇心。

在OS X联机帮助页中有一个关于此的说明:

  

gamma()和gamma_r()已弃用,不应使用。该   应该使用tgamma()函数代替。但请注意,有些人   平台,gamma()和gamma_r()历史上计算了日志   Gamma功能,而不是Gamma功能本身。移植时   来自这些平台的代码,有必要使用lgamma()或   lgamma_r()代替。

长话短说,不要使用gamma。无论如何,这是非标准的。使用标准函数tgammalgamma代替(或者可能是重入的posix扩展名lgamma_r。)