26

这是一个非常简单的问题:为什么pi、pi/2、pi/4、1/pi 和 2/pi有预定义的常量,而 2*pi 没有?背后有更深层次的原因吗?

这个问题与整个pi vs tau 辩论无关。我想知道是否有实现某些常量而不是其他常量的技术原因。我能想到两种可能:

  1. 避免舍入错误。
  2. 避免可能更昂贵的运行时划分。
4

2 回答 2

6

2*M_PI 这么难写吗?

说真的,曾几何时,当人们担心可能不会进行常量折叠和除法的简单编译器过于昂贵时,拥有一个常量 PI/2 而不是冒着运行时除法的风险实际上是有意义的。在我们的现代世界中,人们可能只定义 M_PI 并收工,但其他变体仍然存在以实现向后兼容性。

于 2012-11-17T01:19:10.280 回答
4

这只是我的猜测。

我想这些常量与数学库中不同函数的实现有关:

ck@c:~/Codes/ref/glibc/math$ grep PI *.c
s_cacos.c:  __real__ res = (double) M_PI_2 - __real__ y;
s_cacosf.c:  __real__ res = (float) M_PI_2 - __real__ y;
s_cacosh.c:                    ? M_PI - M_PI_4 : M_PI_4)
...
s_clogf.c:      __imag__ result = signbit (__real__ x) ? M_PI : 0.0;
s_clogl.c:      __imag__ result = signbit (__real__ x) ? M_PIl : 0.0;
ck@c:~/Codes/ref/glibc/math$ 

M_PI, M_PI_2, 并且M_PI_4经常出现,但没有2.0 * M_PI。所以对于 Hanno 最初的问题,我认为 MvanGeest 是对的 --- 2π 并没有那么有用,至少在实现libm.

现在关于M_PI_2M_PI_4,它们的存在是有充分理由的。GNU C 库的文档表明“这些常量来自 Unix98 标准并且在 4.4BSD 中也可用”。那个时候编译器还没有那么聪明。键入M_PI/4而不是M_PI_4可能会导致不必要的除法。尽管现代编译器可以对此进行优化(gcc 从 2008 年开始使用 mpfr,因此即使舍入也可以正确完成),但使用数字常量仍然是编写高性能代码的更可移植的方式。

于 2012-11-17T05:13:33.857 回答