2022年9月26日,程序员Casey Muratori在他的个人专栏Computer, Enhance!上发了一篇标题很挑衅的短文——《Turns are Better than Radians》。他没有掺和十年前那场“该用π还是该用τ”的争论,而是抛出一个更激进的判断:两个常数都该从代码里删掉,程序压根不该用弧度制。
判断有具体证据。他随手打开开源游戏引擎Godot的源码,在color_picker.cpp里翻到一行典型写法:一个本来落在0到1区间的比例值h,先乘以Math_TAU转成弧度,再传进sin函数。再往下看sin函数自己常见的AVX2实现,第一步却是把输入乘以1.27323954473516——这个数正好是4除以π。调用方乘π,库函数立刻把π除回去,一进一出,白费一次乘法。
一次自己制造出来的麻烦
几乎所有快速三角函数库,进入函数体第一步都要做range reduction,把任意弧度值折回一个小区间,这一步天然要用到1/π这类因子。如果调用方本来就是从0到1的周期比例值(时间进度、旋转百分比)出发,先乘2π再让库函数除回去,纯属多绕一圈。
turns的另一个好处常被忽略:0.25、0.5、0.75这类常见角度在浮点数里能精确表示,对应的弧度值不管用多少位小数都凑不出来。这不只是省一次乘法,还是精度问题。
CUDA早就这么干了,但没人把它当范式
turns不是Muratori凭空造的概念,它在数学史上本就有名字,也已经悄悄进了工业界。CUDA提供的sincospi这个内置函数,直接计算sin(πx)和cos(πx),输入单位其实就是半turn——一个圆是[0,2]而不是[0,2π]。想用turns思路又不想自己重写三角函数库的人,理论上现在就能切换调用方式,不用碰底层实现。
十年前那场π与τ之争,其实吵在了错误的靶子上。
问题是,Muratori这篇文章从头到尾没有给出一份完整的性能或精度基准测试。他的证据停留在代码层面的逻辑推演——展示两段代码,指出乘除相消——却没有实测数据证明这个优化在真实硬件上能省下多少时间。
- 风险.“turns更快更准”目前更接近一个有说服力的工程直觉,而不是经过严格测量的结论,照单全收前值得多留一个问号。
弧度制真正扔不掉的地方
Muratori自己也承认,弧度制在微积分语境下不可替代。sin(x)求导等于cos(x)这类经典恒等式,成立的前提就是自变量以弧度计量。任何涉及导数、级数展开、连续物理仿真的场景,需要的是弧度制背后的数学结构,不只是习惯用法——这条边界原文一笔带过,却是判断turns能不能全面铺开的关键限制。
游戏与嵌入式行业其实早就发展出比turns更完整的角度表示生态:需要跨设备bit级一致的网络同步用BAM(二进制角度整数),没有浮点单元的嵌入式芯片靠CORDIC算法和定点数逼近三角函数,渲染和动画插值才轮到turns或半turns这类浮点归一化方案。turns作为浮点数,本身也不保证不同硬件算出完全一致的比特结果,遇到需要严格确定性的场合,工程师照样得退回整数BAM。
- 结论.写渲染、动画、UI插值代码时,把角度参数从弧度换成turns基本是纯收益;一旦代码涉及求导、级数或跨机确定性同步,弧度制或整数角度依然是更稳的选择。
这也是为什么C标准库的sin、cos至今只认弧度参数:不是没人想到turns,是迁移成本卡在了那些真正离不开弧度数学结构的场景上。库函数内部的转换代码永远存在,能删掉的只是调用方那一层多余的乘法——这一步值得每个写图形代码的人现在就检查一遍自己的项目。
