Python 测试两条线段相交时的算术精度问题
我编写了一个测试平面中两条线段相交的代码。我不会为所有的细节打扰你 代码采用两条线段,每条线段由两个端点描述,然后通过在y=a*x+b中拟合a和b将每条线段拟合到一条直线上。然后通过x=b2-b1/a2-a1找到两条线的交点。最后,它测试交点x是否包含在两条线段内 相关部分如下所示:Python 测试两条线段相交时的算术精度问题,python,floating-point,precision,Python,Floating Point,Precision,我编写了一个测试平面中两条线段相交的代码。我不会为所有的细节打扰你 代码采用两条线段,每条线段由两个端点描述,然后通过在y=a*x+b中拟合a和b将每条线段拟合到一条直线上。然后通过x=b2-b1/a2-a1找到两条线的交点。最后,它测试交点x是否包含在两条线段内 相关部分如下所示: # line parameterization by a = Delta y / Delta x, b = y - a*x a1 = (line1.edge2.y - line1.edge1.y) / (line1
# line parameterization by a = Delta y / Delta x, b = y - a*x
a1 = (line1.edge2.y - line1.edge1.y) / (line1.edge2.x - line1.edge1.x)
b1 = line1.edge1.y - a1 * line1.edge1.x
a2 = (line2.edge2.y - line2.edge1.y) / (line2.edge2.x - line2.edge1.x)
b2 = line2.edge1.y - a2 * line2.edge1.x
# The intersection's x
x = - (b2 - b1) / (a2 - a1)
# If the intersection x is within the interval of each segment
# then there is an intersection
if (isininterval(x, line1.edge1.x, line1.edge2.x) and
isininterval(x, line2.edge1.x, line2.edge2.x)):
return True
else:
return False
为了简洁起见,我放弃了很多处理特定情况的测试,比如当边彼此平行时a1==a2,当它们在同一条线上时,当边的长度为0,当边沿垂直轴时,a变为无穷大等
函数isininterval非常简单
def isininterval(x0, x1, x2):
"""Tests if x0 is in the interval x1 to x2"""
if x1 <= x0 <= x2 or x2 <= x0 <= x1:
return True
else:
return False
现在的问题是:我发现由于舍入误差,当交点与线段边缘重合时,测试将给出错误的结果
例如,如果第1行介于0,0和3,5之间,第2行介于3,5和7,1之间,则生成的交点x为2.9999999996,这将给出错误答案。应该是3岁
你能提出一个解决方案吗?这是浮点运算的一个问题/特点。通过以某种方式对指令进行排序,可以将错误降至最低,但最终,您将得到近似的答案,因为您可能用有限的位数来表示无限数 您需要定义您构建的任何函数,使它们能够容忍这些错误。看看您的示例,正确的值与您得到的值之间的差值为1e-16级-非常低
对于不等式,尤其是等式,放松精确/位匹配的约束是值得的。例如,如果您想测试x==3,您可以将其写成absx-3
对于不等式,尤其是等式,放松精确/位匹配的约束是值得的。例如,如果您想测试x==3,您可以将其写成absx-3