计算器算出了32°,为什么目标却在相反方向?
两个相反方向能有相同的斜率。只留下一个比值,就丢掉了你真正需要的符号。
你知道目标在左下方,程序却画了一条朝右上的箭头。算式也许没敲错:如果先把两个负数相除,得到的正比值已经无法告诉你目标到底在哪个象限。
打开互动课程 →
先猜一下
向右上和向左下的两条线,y/x比值可能一样吗?
查看答案与解释
可能 — 两分量同时变号,比值不变,但方向相差180°。
再把体验和科学连起来
先认清目标所在的象限
蓝色点的位置由x与y共同决定。单参数atan只读比值,两个负号会在除法里抵消。
atan(y/x)的返回范围只有−90°至90°
把两个分量分别交给atan2
atan2(y,x)保留正负号,可以区分左下与右上;它的参数顺序要按语言文档确认。
本项目使用 Math.atan2(y,x)
方向正确,还要用对角度单位
JavaScript三角函数输入为弧度。把212这样的度数直接交给sin,会把它误认为212弧度。
弧度 = 度 × π/180
特殊情况不能靠假数蒙混过去
轴上方向可以定义,零向量却不能。负数的向下取整与截断也不同,历法代码尤其不能混用。
atan2(0,0)无几何方向;floor(−7.83)=−8
把计算链展开
θ弧度 = atan2(y,x) θ度 = θ弧度 × 180/π θ圈内 = ((θ度 mod 360)+360) mod 360
atan2先传y,再传x;它保留象限信息。x=y=0时没有几何方向,即使程序返回数值也不能当作方向。
试一试
先看原书左下方例,再把两个分量都改成正数。斜率比值一样,但方向必须相差半圈;最后试零向量。
动手看一遍 →
符号不用背
- atan(y/x)
- 只看比值,无法独自区分相差180°的方向
- atan2(y,x)
- 分别保留两个分量,判断象限
- θ / θπ/180
- 角度值(度)/对应弧度值
- floor / trunc
- 向负无穷取整 / 向零截断,两者不是同一操作
算法、精度与适用范围
补第1章正确象限与语言单位陷阱。使用原书A=−0.5712、B=−0.9139,界面y=A、x=B;atan(A/B)约32°而正确方向约212°。单参数atan在x=0时不作除法演示;atan2仍可判定轴上方向,但(0,0)没有几何方向,不能沿用JavaScript atan2(0,0)=0而伪造答案。右图比较同一角度转换成弧度后与误把度数直接交给Math.sin的结果;同时展示仅由cos反推时的0–180°范围。负数floor/trunc取整与第7章一致。旧角度入门课已有度分秒负号、角度小时和绕圈;此处不重复它。数学入口另实现原书大角归一化测试、Horner多项式和数值周期项表求和,核对与直接展开一致;不把旧机型速度测试推论成现代JavaScript性能保证。安全分支与迭代上限的实作另见一般求根课。
我的理解检查
本项目用哪种函数保留两个分量的符号?
atan2(y,x) — atan2分别接收y和x,不先丢掉象限信息。
θ以度表示时,可以直接Math.sin(θ)吗?
不可以,先换弧度 — JavaScript的sin输入是弧度。
两个分量都为0,正确的方向应怎样报告?
没有定义 — 零向量没有方向;函数返回的数字不能替代几何定义。
先保留方向分量与符号,再转换单位;程序给出数字,不代表那个数字有正确的几何含义。
Jean Meeus · Astronomical Algorithms, 2nd ed. · 第 1 章