处理基本案例时的编程理念

时间:2014-03-22 19:55:46

标签: algorithm

我正在修补一个功能,测试矩形和圆圈之间的交叉点以及我有四个案例进行测试的原始函数。他们是:

1。)如果圆的边界矩形与矩形不相交,则返回False

2。)如果矩形的任何点位于圆圈中,则返回True

3.)如果圆的中心位于矩形中,则返回True

4。)迭代矩形中的线条并分别测试圆圈的交点。如果有任何交叉点,则中断并返回True。

但是在使用timeit对函数进行计时时,我意识到实际上平均更快地省略了案例1-3并且仅仅使用4来测试碰撞(平均而言,速度增加了100%) ,它是1000次测试的两倍。

我最初实现了所有四种情况,因为更常见的情况(1 - 3)会在返回True时快速终止函数,但我想我认为错了。所以我的问题是,你的家伙是什么?在编程和会计不同场景时的哲学?您是尝试实施一种始终有效的算法,还是三种或四种算法,每种算法的成本都比单独的算法低得多?

以下是代码,如果您想要查看它,它有点无用,因为它依赖于我已经制作的其他东西,但您可能能够了解发生了什么:

    def collide_rect(self, rect):
        """Check if the circle collides with a rect."""
##        if not rect.collide_rect(self.to_rect()):
##            # Case 1 ~ The bounding rects don't intersect.
##            return False
##        # Case 2 ~ One of the points on the rect is inside the circle.
##        points = rect.points()
##        if any(self.collide_point(v) for v in points):
##            return True
##        if rect.collide_point(self._center):
##            # Case 3 ~ The circle is entirely contained by the rect.
##            return True
        # Case 4 ~ None of the points from the rect fall inside
        # the circle. Now we must check if any of the lines from
        # the rect intersect the boundaries of the circle. To do
        # this, we know that if a line intersects a circle's boundary,
        # then there exists some value `t` such that 0 <= `t` <= 1
        # (i.e. `t` is a ratio), and the distance from the point at
        # ratio `t` on the line segment is also the radius of the circle.
        points = rect.points()
        _abs = abs
        for i in range(4):
            start = points[i - 1]
            end = points[i]
            _line = Segment(start, end)
            if _line.isHorizontal():
                if (_line._s.x < self.x < _line._e.x) or \
                   (_line._s.x > self.x > _line._e.x)    :
                    if _abs(_line._s.y - self.y) <= self.r:
                        return True
                else:
                    dist1 = (_line._s.x - self.x)**2 + (_line._s.y - self.y)**2
                    dist2 = (_line._e.x - self.x)**2 + (_line._e.y - self.y)**2
                    if dist1 <= self.r**2 or dist2 <= self.r**2:
                        return True
            elif _line.isVertical():
                if (_line._s.y < self.y < _line._e.y) or \
                   (_line._s.y > self.y > _line._e.y)    :
                    if _abs(_line._s.x - self.x) <= self.r:
                        return True
                else:
                    dist1 = (_line._s.x - self.x)**2 + (_line._s.y - self.y)**2
                    dist2 = (_line._e.x - self.x)**2 + (_line._e.y - self.y)**2
                    if dist1 <= self.r**2 or dist2 <= self.r**2:
                        return True
        return False

(代码的注释部分是删除的案例1-3。)

1 个答案:

答案 0 :(得分:2)

问题是:最后一个算法是否足够快?如果您没有任何性能问题,则不必担心其他情况。

一个案例仅意味着更少的代码,因此更少的错误和更容易的维护。

正如在计算机科学中经常说的那样,过早的优化是万恶之源;) 所以从测试性能开始,如果由于碰撞检测不够好,则通过添加其他测试之一进行优化。然后迭代:)