ValueError: math domain error ってなに?

AOJのこの問題を解くのに次のようなコードを書いた。

import sys
import math

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

class Vector:
    def __init__(self, p1, p2):
        self.vx = p2.x - p1.x
        self.vy = p2.y - p1.y

    def length(self):
        return math.sqrt(self.vx ** 2.0 + self.vy ** 2.0)

    def degree(self, other):
        theta = math.acos((self.vx * other.vx + self.vy * other.vy)/(self.length() * other.length()))
        return theta

    def show(self):
        return "Vector(%f, %f)" % (self.vx, self.vy)

def solv(points):
    p0 = points[0]
    for p in points[1:]:
        if p.y < p0.y:
            p0 = p
            v1 = Vector(Point(0.0, 0.0), Point(1.0, 0.0))
            p1 = p0
            t = [p1]
    while True:
        min_deg = math.pi
        next_p = None
        next_v = None
        points2 = list(points)
        points2.remove(p1)
        for p2 in points2:
            v2 = Vector(p1, p2)
            deg = v1.degree(v2)
            if deg < min_deg:
                min_deg = deg
                next_p = p2
                next_v = v2
            if next_p == p0:
                break
            p1 = next_p
            t.append(p1)
            v1 = next_v
         return len(points) - len(t)
    while True:
        n = int(sys.stdin.readline())
        if n == 0:
            break
        points = []
        for i in range(n):
            x, y = map(float, sys.stdin.readline().split(','))
        points.append(Point(x, y))
    print solv(points) 

複数の点が与えられて、凸包の中にある点の数を出力する問題で、ググってあちこちのページを参考にしながら書いたので、エレガントじゃないとかそういうことは置いといてたぶんあってる。 簡単に説明しておくと、一番下の点を出発点として左回りに凸包に含まれる点を探索している。この時、すでに凸包に含まれるのが明らかになっている最後の2点を結ぶベクトルと、最後の1点とその他の点を結ぶベクトルのなす角度をそれぞれ求めて、角度が最も小さい点を次の点としている。で、最初の点に戻ってくるまでループしてるわけだ。 さて、これにサンプルのデータを与えて実行するとタイトルのようなエラーが出る。

^o^ > python problem0-0068.py < input0-0068.txt
0
Traceback (most recent call last):
  File "problem0-0068.py", line 70, in 
    print solv(points)
  File "problem0-0068.py", line 48, in solv
    deg = v1.degree(v2)
  File "problem0-0068.py", line 25, in degree
    theta = math.acos((self.vx * other.vx + self.vy * other.vy)/(self.length() *
 other.length()))
ValueError: math domain error

math.acos()のところでエラーになっている。ここには載せないけどサンプルの入力データには2つのデータセットがあって、1つ目のデータセットに対する出力は正常にされている。最初の0がそうだ。これはサンプルの回答ともあっている。だけど2つ目のデータセットではエラーが発生する。
詳しく調べてみると、math.acos()の引数が-1.0の時にエラーになっているんだけど、引数が-1.0になるのは1度じゃなく何度もあって、エラーが発生しないときもある(というか発生しないほうが多い)。実際1つ目のデータセットには正解を返してるわけだし。

ググってみてもこの math domain error というのがどういうエラーなのかよくわからない。

いくら悩んでもわからないので、ダメもとでAOJに提出したら、あっさりとAcceptedになってしまった。

わけがわからないよ。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください