質問: dot(r); //return f; if( f <= 0.0f) { printf("鈍角: %f\n", f); //printf("鈍角: %.2f\n",f); return false; }else { //printf("鋭角: %.2f\n", f); printf("鋭角: %f\n", f); return true;// } } ```
回答: 浮動小数点数に関する誤差の扱いは非常にデリケートな問題です。「`==` 比較をしてはいけない」といった単純なルールで対応しきれるものではなく(実際 `==` で比較してもいい場合も稀にあります)、毎回ケースごとにどう処理するべきかをいちいち考えて対応しなくてはなりません。今回の場合にどうすればよいかをここで説明します。 今回のコードは2つのベクトルの位置関係で分岐を行うものだと思われます。具体的には、2つのベクトル A と B がなす角を θ とすると、ベクトルの内積は A・B = |A||B|cosθ となります。したがって、内積が正のときは 0° <= θ < 90° (鋭角)、負のときは 90° < θ <= 180°(鈍角)というのがもとのコードの意図であると思われます。 今回の質問は、要するに「内積がちょうど厳密に 0 になるときはどうすればよいか?」ということです。内積がちょうど0になるのは2つのベクトルが直交するとき、つまり θ = 90° のときです。あなたのプログラムはこのようなケースを扱う必要があるでしょうか? もしそのようなケースがあり得ないのであれば `<=` でも `<` でも同じです。もしそういうケースを扱う必要があるのであれば、その場合のコードを書き足す必要があります。 内積が厳密な計算によって 0 になる場合でも、浮動小数点数の計算誤差によってプログラム内では内積がちょうど 0 にならないかもしれません。その場合でも、内積の値は 0 に極めて近い値になっていると考えられます。したがって、適当に小さな値 ε を定めて内積が -ε と ε の間にあれば内積が 0 であるとみなして処理することになります。 具体的には、最初に以下のような比較文を追加する形になります。 ``` if (-1e-9 < f && f < 1e-9) { // 1e-9 は 0.000000001 のこと // 2ベクトルが直交する場合の処理 } ... // 残りの分岐 ``` なお、ここで比較に `<` を使うのと `<=` を使うのとには大きな差がなく、どちらを使っても構いません。なぜなら、`f` が `-1e-9` や `1e-9` に厳密に一致することはあり得ないものと想定しているからです。もしそうなり得るのであれば誤差の許容範囲を表す値 ε = `1e-9` を設定しなおす必要があります。