裏表(Phinloda のもう裏だか表だか分からないページ)

コンピュータ・プログラミング系の話がメインのそれなりにごちゃごちゃしたネタばかり出てくるサイトです。多分。
<< Mechanize で Firefox 15.0.1 の user_agent を指定する | Top | Firefox 16.0.1 >>
直線と点との距離を求める

知恵袋に、直線と点との距離を求めるにはどうするかという質問があったので、C言語で書いてみたら、最終的に、こんな感じになった。

#include <math.h>

double distance(double lineX1, double lineY1, double lineX2, double lineY2,
    double dotX, double dotY) {
    double a, b, c; /* ax + by + c = 0 */
    double root;
    double dist; /* 求める距離 */

    a = lineY1 - lineY2;
    b = lineX2 - lineX1;
    c = (-b * lineY1) + (-a * lineX1);
    root = sqrt(a*a + b*b);

    if (root == 0.0) {
        return -1.0; /* 求められない場合は負の値を返す */
    }

    dist = ((a * dotX) + (b * dotY) + c) / root;

    if (dist < 0.0) {
        dist = -dist;
    }

    return dist;
}
公式などは調べたら分ると思うので説明は省く。単に公式に当てはめているようなものである。 ところで、これは実は投稿後に修正したのである。 厳密にいえば細かいところは違っているが、 修正前のロジックの一部は次のような感じだった。
    a = lineY1 - lineY2;
    b = lineX2 - lineX1;

    if (a == 0.0 && b == 0.0) {
        return -1.0; /* 求められない場合は負の値を返す */
    }

    c = (-b * lineY1) + (-a * lineX1);
    root = sqrt(a*a + b*b);

    dist = ((a * dotX) + (b * dotY) + c) / root;

修正した理由は、a == 0.0 && b == 0.0 が成立しなくても、sqrt(a*a + b*b) が 0.0 になることがあるだろうと考えたからである。 a も b も 0.0 に極めて近い場合に a*a も b*b も 0.0 になってしまう可能性があるから、おそらくこの判断は正しい。

修正前のロジックは、sqrt の処理は比較的重いだろうと考えて、呼び出す前にエラーになる場合を判定しようと考えたのだ。 だから、この判定は c を計算する前に行っている。エラーになるのなら、判定前に c を計算するのは無駄だ。

ところで、sqrt(x) において、x > 0 であれば、sqrt(x) > 0 であることは保証されるか? もしその保証があれば、sqrt を呼び出す前に、a*a + b*b の値が 0.0 かどうかを比較した時点でエラーチェックすることができる。

確かめてみると、ISO の draft (2007/9/7版) を見ても、引数が less than zero だと domain error になると書いてあるが、それだけである。 数学的には、0 < x < 1 の場合に、x < √x が成り立つのだから、x > 0 であれば sqrt(x) > 0 も成り立って欲しいのだが、0に極めて近い値が与えられたときに、実装の制限によって0が返される可能性があるかどうか、そこがどうも分らない。

ということで、確実なのは sqrt を求めた後に 0.0 と比較することだろうという結論に至ったのである。

JUGEMテーマ:コンピュータ
| C言語 | 11:07 | comments(0) | trackbacks(0)
スポンサーサイト
| - | 11:07 | - | -
コメント
コメントする









この記事のトラックバックURL
http://phinloda.jugem.cc/trackback/3198
トラックバック
Powered by "JUGEM"
▲このページの先頭へ
CALENDAR
S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526272829
3031     
<< July 2017 >>
NEW ENTRIES
CATEGORIES
ARCHIVES
NEW COMMENTS
NEW TRACKBACKS
LINKS
PROFILE