在不幸的情况下,我发现我的标准库实现<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!
答案 0 :(得分:4)
总结:历史上的困惑比比皆是;避免gamma()
并使用tgamma()
。
实现这些功能的是数学库,而不是gcc(编译器)。如果你在MacOS和Ubuntu上看到不同的行为,可能是因为Ubuntu使用glibc而MacOS使用其他东西。
ISO C标准库中没有名为gamma
的函数。
有一些名为lgamma
和tgamma
的标准函数。引用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引入的。
不推荐使用这些功能:而是使用 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 -pedantic
或gcc -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左右),gamma
为lgamma
(gamma函数的日志)。在其他平台上(osx和bsd post-4.4ish),它是tgamma
(“真正的”伽玛函数)。这是一种历史的好奇心。
在OS X联机帮助页中有一个关于此的说明:
gamma()和gamma_r()已弃用,不应使用。该 应该使用tgamma()函数代替。但请注意,有些人 平台,gamma()和gamma_r()历史上计算了日志 Gamma功能,而不是Gamma功能本身。移植时 来自这些平台的代码,有必要使用lgamma()或 lgamma_r()代替。
长话短说,不要使用gamma
。无论如何,这是非标准的。使用标准函数tgamma
和lgamma
代替(或者可能是重入的posix扩展名lgamma_r
。)