🐙

acosで求める角度とatan2で求める角度の差

2022/09/19に公開

ことの発端

「acos関数は引数が1または-1に近いと精度が悪い」という話を見かけました.
言われてみれば,浮動小数点数で表すことのできる精度には限界があるので,角度の小さい範囲では角度の変化に対するcosの変化量が少なくacosで求める精度は悪化しそうです.

実際にどれくらいずれるのか

32bit浮動小数点数で計算した場合どれくらいずれるのか,実際に計算してみました.

計算に使ったプログラムはこちら

fn main() {
    println!("i, theta[rad], theta[deg], from acos, from atan2");
    for i in 0..=10000 {
        let theta_rad = std::f32::consts::PI * i as f32 / 10000.;
        let theta_deg = theta_rad * 180. / std::f32::consts::PI;
        let cos = theta_rad.cos();
        let sin = theta_rad.sin();
        println!(
            "{}, {}, {}, {}, {}",
            i,
            theta_rad,
            theta_deg,
            cos.acos(),
            f32::atan2(sin, cos)
        );
    }
    println!("Finish!");
}

0~180度の範囲の10000点でそれぞれacosとatan2で角度を求めてみました.

結果をプロットしたものがこちら
横軸は真値の角度[degree]で縦軸がそれぞれacosで計算した場合とatan2で計算した場合の計算誤差です.

atan2で求める角度の計算誤差は0度に近づくにつれて減少していっていますが,acosで求める角度の計算誤差は増加していっています.

15度以下の範囲で特に差が大きそうだったので0度から15度の範囲の10000点でプロットしてみたものがこちらです.

誤差の絶対値がかなり大きいわけではなさそうですが,使用する範囲とどれくらいの誤差範囲に収めたいかで注意する必要がありそうです.

Discussion