这是一个非常简单的问题:为什么pi,pi/2,pi/4,1/pi和2/pi有预定义的常量,而2 * pi没有?这背后还有更深层次的原因吗?
这个问题不是关于整个圆周率与tau的辩论。我想知道是否有技术原因来实现某些常量而不是其他常量。我能想到两种可能性:
- 避免舍入误差。
- 避免可能更昂贵的运行时划分。
2*M_PI这么难写吗?
说真的,曾几何时,当人们担心简单的编译器可能不会进行常量折叠并且除法过于昂贵时,拥有一个恒定的 PI/2 而不是冒运行时除法的风险实际上是有意义的。 在我们的现代世界中,人们可能只是定义M_PI并将其称为一天,但其他变体继续存在以向后兼容。
这只是我的猜测。
我想这些常量与数学库中不同函数的实现有关:
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_2
和M_PI_4
,他们的存在是有充分理由的。 GNU C库的文档表明"这些常量来自Unix98标准,并且在4.4BSD中也可用"。 当时的编译器并没有那么聪明。 键入M_PI/4
而不是M_PI_4
可能会导致不必要的划分。 尽管现代编译器可以对此进行优化(gcc 自 2008 年以来一直使用 mpfr,因此即使舍入也可以正确完成),但使用数字常量仍然是编写高性能代码的更便携的方法。