次のfloat型の値が等しいかどうかを比較しようとしているんだけど…
等しくなるはずなのに、値が違う判定になっちゃうの
これは、浮動小数点誤差によるものだね。aとbは一見等しいように見えて、微妙に値が異なっているの。
C#言語で扱うfloat型やdouble型などの浮動小数点数は、計算することで値の丸め誤差が発生してしまいます。
例えば、1.1 – 1.0という計算は値が0.1になるはずですが、2進数で表すと割り切れない数となり0.1とは微妙に異なる数になってしまいます。
このような浮動小数点数同士が等しいかどうかを比較したい場合、両者の差がある一定値以内ならほぼ等しいとみなすことで回避可能です。
また、Vector3構造体など、幾つかのUnity提供型の等価演算では、内部的にこのような比較処理を行っています。
本記事では、このような浮動小数点数のほぼ等しい判定を行う方法を解説していきます。
- Unity2021.1.24f1
- .NET 4.x
目次 非表示
Mathf.Approximately()メソッドを使う
与えられた2つのfloat型の値がほぼ等しいかどうかを判定するメソッドです。
引数には比較対象の浮動小数点数を指定します。
戻り値は、引数の値がほぼ等しければtrue、そうでなければfalseです。
参考:Mathf-Approximately – Unity スクリプトリファレンス
サンプルスクリプト
2つの値がほぼ等しいかを判定するサンプルスクリプトです。
実行結果
デバッグログの出力結果です。
1つ目の丸め誤差があるケースでは、ほぼ等しい判定になります。
2つ目の大きな数同士の比較では、誤差が1という大きな誤差があるにも関わらずほぼ等しい判定になります。大きな数になると値の精度が落ちるため、大きな数の比較では閾値を広げる処理が内部的に行われています。
3つ目の大きな数が大きく異なるケースでは、ほぼ等しくない判定になります。
Vector2やVector3の等価演算について
ベクトル同士の比較を行いたい場合、次のように==演算子でほぼ等しい判定ができます。
参考:Vector2-operator == – Unity スクリプトリファレンス
参考:Vector3-operator == – Unity スクリプトリファレンス
サンプルスクリプト
実行結果
さいごに
float型同士の値がほぼ等しいかどうかを判定するには、Mathf.Approximately()を用いれば良いです。
Vector2やVector3型など、Unityが提供しているいくつかの型の等価演算では、内部的にほぼ等しい判定を行っています。
そのため、組み込み型の浮動小数点数の等価演算を行う場合に注意すると良いでしょう。