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

2024-05-01

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

double gamma(double x);

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

在 Mac OS X 上使用 gcc v4.2.1 该函数的计算结果与tgamma这实际上是标准中给它的名称。(参考) http://www.cplusplus.com/reference/cmath/tgamma/

但在 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!


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

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

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

有一些标准函数称为lgamma and tgamma。引用N1570 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf(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);

The lgamma函数计算绝对值的自然对数 的伽马值x。如果出现以下情况,则会发生范围错误x太大了。一根杆子 如果出现以下情况,可能会发生错误x是负整数或零。

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

The tgamma函数计算伽马函数x。域错误 否则可能会发生极错误,如果x是负整数或零。范围 如果大小发生错误x太大并且可能发生,如果 的大小x太小。

这些函数没有出现在 1990 年的 ISO C 标准中。它们是由 C99 引入的。

引用Linux 手册页gamma http://man7.org/linux/man-pages/man3/gamma.3.html:

这些函数已被弃用:相反,使用tgamma(3) 或 这lgamma(3) 适当的职能。

关于Gamma函数的定义,请参见tgamma(3).

  • *BSD版本

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

  • glibc版本

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

以及历史记录:

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

“在未来的某个时候,伽玛这个名字将会被恢复, 用于伽玛函数"

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

Since gamma不是标准 C 函数,编译时使用gcc -std=c99 -pedantic or gcc -std=c11 -pedantic应该至少对任何调用它的尝试产生警告。

你可能应该使用tgamma() (or lgamma()如果你想要自然对数)并避免使用gamma().

C标准似乎没有说明Gamma函数是什么。这Linux tgamma() 手册页 http://man7.org/linux/man-pages/man3/tgamma.3.html确实(但如果您尝试使用它,您可能已经知道它是什么):

伽马函数定义为

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

它是为除非正整数之外的每个实数定义的。
对于非负积分 m 有

伽马(m+1) = m!

更一般地,对于所有 x:

伽玛(x+1) = x * 伽玛(x)

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gamma(double x) 的定义是什么以及为什么它在两个 gcc 版本上不同? 的相关文章

  • AVX512 掩码寄存器(k1...k7)的 GNU C 内联 asm 输入约束?

    AVX512 为其算术命令引入了 opmask 功能 一个简单的例子 上帝螺栓 org https godbolt org z P7xWD8 include
  • 使用基类指针创建对象时缺少派生类析构函数

    在下面的代码示例中 未调用派生类析构函数 知道为什么吗 我有一个具有虚函数的基类 现在我使用基类指针来创建派生类的新对象 我的理解是 当派生类对象被销毁时 首先调用派生类的析构函数 然后调用基类 但是我只看到基类的析构函数被调用 有谁知道我
  • 使用动态链接器包装 glibc 函数

    我正在尝试包装 GLIBCfstat通过将我的库注入可执行文件来实现函数 可以是任何其他 这只是概念证明 我通过将我的库放置在可执行文件的位置来做到这一点RPATH用名字指着libc so 6 我的库的源代码如下 define GNU SO
  • 列出 C 常量/宏

    有没有办法使GNU C 预处理器 cpp 或其他一些工具 列出给定点上的所有可用宏及其值C file 我正在寻找特定于系统的宏 同时移植一个已经精通 UNIX 的程序并加载一堆稀疏的 UNIX 系统文件 只是想知道是否有比寻找定义更简单的方
  • 使用 -static-libgcc -static-libstdc++ 编译仍然会导致对 libc.so 的动态依赖

    我正在尝试制作一个尽可能可移植的可执行文件 删除一些依赖项后 我在另一个系统上运行二进制文件时遇到以下问题 lib x86 64 linux gnu libm so 6 version GLIBC 2 15 not found requir
  • 如何BSWAP 64位寄存器的低32位?

    我一直在寻找如何将 BSWAP 用于 64 位寄存器的低 32 位子寄存器的答案 例如 0x0123456789abcdef位于 RAX 寄存器内 我想将其更改为0x01234567efcdab89用一条指令 因为性能 所以我尝试了以下内联
  • 软件预取手动指令合理的场景

    我读过有关 x86 和 x86 64 Intel 的内容gcc提供特殊的预取指令 include
  • Fedora 21 带 clang,不带 gcc

    你能 合理地 让 Fedora 21 变得只有 llvm clang libc libc abi 吗 我发现有些东西暗示不可以 但它们都已经有 3 岁了 从那时起 llvm clang 已经取得了长足的进步 通过全新安装 我尝试了 yum
  • 在64位操作系统上以32位模式和64位模式编译ioctl函数的执行有什么不同?

    我有 64 位 Enterprise SuSE 11 我有一个应用程序 它打开 HIDRAW 设备并在其上操作 ioctl 函数以从该设备获取原始信息 如下所示 struct hidraw devinfo devinfo int fd op
  • 为什么 -march=native 很少使用?

    对于大多数 C C 编译器 有一个可传递给编译器的标志 march native 它告诉编译器调整为主机 CPU 的微架构和 ISA 扩展生成的代码 即使它的名称不同 基于 LLVM 的编译器通常也有一个等效的选项 例如rustc or s
  • 错误:“std::this_thread”尚未声明

    我尝试使用 std this thread sleep for 函数但收到错误 error std this thread has not been declared 包括标志 GLIBCXX USE NANOSLEEP 还需要什么来强制它
  • gcc 不太可能使用宏

    我正在编写一段关键代码 其逻辑大致如下 if expression is true do something with extremely low latency before the nuke blows up This branch i
  • 代码块 - 使用大地址感知标志进行编译

    如何使用以下命令在 64 位系统上编译 32 位应用程序LARGE ADRESS AWARE使用代码块标记 我需要使用超过 2GB 的内存 应该是添加的情况 Wl large address aware到链接标志 我不使用 CodeBloc
  • GCC:数组类型具有不完整的元素类型

    我已经宣布了struct 我尝试传递这些结构的数组 以及double双精度数组和一个整数 到一个函数中 我得到一个 数组类型具有不完整的元素类型 当我编译它时来自 gcc 的消息 我在通过考试的过程中犯了什么错误struct到函数 type
  • 错误:“uint16_t”未声明? [复制]

    这个问题在这里已经有答案了 我有代码 include
  • 带有适用于 MS-Windows 的工具链的预构建 MIPS 交叉编译器

    我在我的 Linux 机器上使用 MIPS 交叉编译器 效果很好 现在我需要在 Windows 上编译相同的应用程序 我正在网上搜索一些适用于 MS Windows 的预构建 MIPS 交叉编译器 带有工具链 但没有成功 由于我不确定该怎么
  • 为什么 GCC 交叉编译不构建“crti.o”?

    在尝试为arm构建gcc 4 x x交叉编译器时 我陷入了缺失的困境crti o文件在 BUILD DIR gcc子目录 An strace在顶层Makefile表明编译后的xgcc正在调用交联器ld with crti o 作为一个论点
  • 如何编译GCC生成的asm?

    我正在玩一些汇编代码 有些事情困扰着我 我编译这个 include
  • arm-linux-gnueabi 编译器选项

    我在用 ARM Linux gnueabi gcc在 Linux 中为 ARM 处理器编译 C 程序 但是 我不确定它编译的默认 ARM 模式是什么 例如 对于 C 代码 test c unsigned int main return 0x
  • ELF动态符号表

    我有一个关于 ELF 动态符号表的问题 对于 FUNC 类型的符号 我注意到某些二进制文件中的值为 0 但在其他二进制文件中 它具有一些非零值 这两个二进制文件都是由 gcc 生成的 我想知道为什么会出现这种差异 有没有编译器选项来控制这个

随机推荐