数学 / 解三角形 · 六个元素里的三个 / 三角形面积与形状判定 待审核 3 / 4
½ab·sin C · 海伦公式

三角形面积与形状判定

面积公式在初中只有一条:底乘高除以二。高不是三角形的原始元素,要么另测,要么由已知的边与角算出来。把「算高」这一步合并进公式,就得到几个只用六个元素的表达式。它们在数学上等价,在浮点下不等价,而分歧之大超出直觉。

1 · 由两边与夹角给出的面积

ABAB 为底,高是 CCABAB 的距离。由 余弦定理与边角互化 §1 的坐标摆法,CC 的纵坐标是 bsinAb\sin A,这就是高。代入底乘高除以二:

S=12bcsinA=12casinB=12absinCS = \frac{1}{2}bc\sin A = \frac{1}{2}ca\sin B = \frac{1}{2}ab\sin C

三式由字母轮换给出,用哪一式取决于已知的是哪两条边与哪个夹角。sin\sin(0°, 180°)(0°,\ 180°) 上恒为正,所以不必像余弦定理那样操心符号。

配上正弦定理还能换出两个常用形式。把 sinA\sin A 换成 a/(2R)a/(2R)S=abc4RS = \dfrac{abc}{4R};用内切圆半径 rr 与半周长 ss 则有 S=rsS = rs,后者的来历是把三角形按内心切成三块,每块以一条边为底、以 rr 为高。

2 · 只由三边给出的面积

三边已知时可以先反解一个角再用 12absinC\frac{1}{2}ab\sin C,但有一条直接的路。在 S=12absinCS = \frac{1}{2}ab\sin C 里把 sinC\sin C 写成 1cos2C\sqrt{1 - \cos^2 C},再把余弦定理的 cosC\cos C 代进去,整理即得海伦公式

S=s(sa)(sb)(sc),s=a+b+c2S = \sqrt{s(s-a)(s-b)(s-c)}, \qquad s = \frac{a+b+c}{2}

这条公式的形式对称,不需要选定哪个角,代价是四个因子里有三个是减法。aabbcc 接近共线时 sas - a 这类因子是两个相近数之差,有效数字大量抵消。Kahan 给出的稳定写法把三边降序排成 xyzx \ge y \ge z,再按

S=14(x+(y+z))(z(xy))(z+(xy))(x+(yz))S = \frac{1}{4}\sqrt{(x + (y + z))\,(z - (x - y))\,(z + (x - y))\,(x + (y - z))}

逐括号计算,每个括号都避开了「大数减大数」。第四条路径与边长无关:三个顶点的坐标已知时,S=12AB×ACS = \frac{1}{2}\left|\overrightarrow{AB} \times \overrightarrow{AC}\right| 只做两次乘法与一次减法。

3 · 四个算法在细长三角形上的分歧

图 3-1 · 四种面积算法并排跑,参照取坐标叉积。可调两条邻边、夹角与压扁指数 kk,观察经过边长的三式何时与参照分道、何时一同归零。

警示 · 「海伦公式在细长三角形上不稳,改用 Kahan 的排序形式即可」这句常见说法只在一小段上成立。顶点取 (0, 0)(0,\ 0)(1000, 0)(1000,\ 0)(500, h)(500,\ h),精确面积是 500h500h,实测:h=102h = 10^{-2} 时海伦的相对误差是 3.97e-7、Kahan 是 1.12e-7,只赢 3.53.5 倍;h=103h = 10^{-3} 时两者只差 11 ulp,相对误差同为 5.29e-6h=106h = 10^{-6} 时两者一同给出 0。根源不在面积公式:h=106h = 10^{-6} 时两条腰的舍入值之和恰好等于底边(a + b === c 为真),三角不等式在浮点下已不成立,高度那点信息在算边长时就丢光了。要精度就不要绕道边长,直接用坐标叉积——它在同一组数据上仍给出 0.0005

这条结论改写了本页原先的叙述。落笔时打算写的是「海伦不稳、Kahan 稳」,实测把前半句保留、后半句推翻:Kahan 的排序形式修的是公式内部的相消,而细长三角形的信息损失发生在公式之前。它仍然值得用(同样的输入不会更差),只是不能当作细长三角形的解药。

4 · 形状判定

面积之外,另一类常见问题是判断形状。钝直锐由最大角定,而最大角必是最大边的对角,所以只需一次符号判断:三边排序为 xyzx \le y \le z 后看 x2+y2z2x^2 + y^2 - z^2 的正负。等腰与等边则只看边长是否相等。两栏互不排斥,等腰直角三角形同时命中。

例 4.1 三边 11112\sqrt{2}1+12=01 + 1 - 2 = 0 判为直角,两条短边相等判为等腰,故为等腰直角三角形。三边 2222224+44=4>04 + 4 - 4 = 4 > 0 判为锐角,三边相等判为等边。三边 112233 不满足严格三角不等式,classify 返回 null 而不是给出一个形状。

「边长相等」的判定同样要走相对容差。用绝对容差时,把整个三角形按同一比例放大一千倍,原本判为等腰的可能就不再等腰了——而形状是相似不变量,不该随尺度改变。classify 里两处容差都以最长边为基准,一处按 z2z^2、一处按 zz

5 · 参考文献

  1. Heron's formula. Wikipedia. 海伦公式的多种证明与数值稳定版本。https://en.wikipedia.org/wiki/Heron%27s_formula
  2. Miscalculating Area and Angles of a Needle-like Triangle. W. Kahan. 细长三角形上面积与角度的失稳分析,排序形式的出处。https://people.eecs.berkeley.edu/~wkahan/Triangle.pdf
  3. Triangle Area. Wolfram MathWorld. 面积的多种表达式,含坐标行列式形式。https://mathworld.wolfram.com/TriangleArea.html
  4. Loss of significance. Wikipedia. 相近数相减导致有效位抵消的一般机制。https://en.wikipedia.org/wiki/Loss_of_significance
  5. Numerical stability. Wikipedia. 稳定性的口径,以及「稳定算法」为何不能修复已损的输入。https://en.wikipedia.org/wiki/Numerical_stability