Java 这两条线会在笛卡尔平面相交吗

Java 这两条线会在笛卡尔平面相交吗,java,math,floating-point,Java,Math,Floating Point,我在《破解编码面试》一书中遇到了这个问题 给定笛卡尔平面上的两条直线,确定这两条直线是否相交` 以下是解决方案: public class Line { static double epsilon = 0.000001; public double slope; public double yintercept; public Line(double s, double y) { slope = s; yintercept =

我在《破解编码面试》一书中遇到了这个问题

给定笛卡尔平面上的两条直线,确定这两条直线是否相交`

以下是解决方案:

public class Line {

    static double epsilon = 0.000001;
    public double slope;
    public double yintercept;

    public Line(double s, double y) {
        slope = s;
        yintercept = y;
    }

    public boolean intersect(Line line2) {
        return Math.abs(slope - line2.slope) > epsilon ||
        Math.abs(yintercept - line2.yintercept) < epsilon;
    }
}
公共类行{
静态双ε=0.000001;
公共双坡;
公共双音干扰;
公用线路(双s、双y){
斜率=s;
yintercept=y;
}
公共布尔相交(第2行){
返回Math.abs(slope-line2.slope)>epsilon||
数学abs(yintercept-line2.yintercept)
为什么没有一个简单的解决方案,如果斜率不同,那么它们会相交。为什么是ε和y截距

在建议中,它说

不要假设斜率和y截距是整数。了解浮点表示法的局限性。切勿检查是否与
==
相等

为什么没有一个简单的解决方案,如果斜坡不是 相同,然后它们将相交。为什么是ε和y截距

该解决方案考虑了由算术引起的近似误差。 因为浮点数并不代表所有可能的实数,而是一个相对较小的子集(在[-1,+1]区间内更密集),所以在处理浮点运算时,通常使用阈值来执行相等性检查


ε值表示一个阈值,在此阈值下,两个不同的浮点值将被视为相等。

首先,因为如果斜率不相同,它们将相交的简单解决方案是不完整的。它们可以具有相同的斜率和截距,因此是相同的


建议中提到的ε是因为计算机中的数字表示不精确。根据数据,双精度a大约有15个精确的计算数字,因此斜率和截距可能会由于之前的计算而产生舍入误差,因此使用==进行简单检查可能会得出它们不相同,而它们只是由于舍入误差而不同。

,数字在处理时都转换成二进制。不可能将大多数浮点数表示为精确的二进制数(因为它们是1和0的无限系列),因此通过截断二进制序列进行近似。例如,浮点数0.1(即:十分之一)不能表示为精确的二进制数,而是由近似值表示,该近似值看起来像0.000110011。。。截断此二进制数会导致潜在的舍入错误,因此精确的等式“==”可能会导致错误响应,而实际上正是此舍入错误给出了假负数。介绍一个ε试图避免这些错误说“任何低于这个数字,我们认为是零”。请参阅的“二进制分数”部分以了解更多信息。

该“解决方案”是错误的

此“解决方案”中隐含的一个概念是,已传递的参数不准确,即在调用
intersect
之前,已对值进行计算,可能会产生舍入错误的结果。因为值中存在错误,所以如果精确计算,则相等的数字是不相等的。为了承认这些是相等的,这个“解决方案”接受一些实际上不相等的值作为相等

这种推理的一个缺陷是,
intersect
例程不知道错误可能有多大,因此没有依据知道它应该使用的
epsilon
的值。理想值可能是零,也可能是一百万。根据提供的信息,所使用的值1e-5在任何工程原理中都没有依据。除此之外,使用绝对错误是没有依据的,正如这段代码所做的那样。根据具体情况,使用的适当公差可能是相对误差、以ULPs命名的误差或其他技术。根本没有理由相信,当传递参数时,该代码将返回
true
,这些参数在理想情况下表示相交线,但以某种未知的方式进行了计算


另一个缺陷是例程错误地接受不相等的相等值。该例程将报告为未与许多相交的线相交。该代码没有解决例程返回错误答案的问题;它只改变了返回错误答案的情况,并且很可能大大增加了错误答案的数量。

您了解测试两个浮点数是否相等的问题吗?@Beta我也需要一些帮助。感谢这正是我在大多数情况下讨厌浮点数据类型的原因。如果我读这个问题,我会假设斜率和截距是实际的数字,而不是浮点表示。java中有一个
BigDecimal
类型,它没有浮点问题-我确信它比
double
运行计算要慢得多,但至少你不会有epsilon胡说八道的问题要处理。打败我们吧。。。作为一名学生(@Kraken),您最终将了解浮点数与整数类型数的存储和运算方式之间的差异,但要记住的主要一点是,20.0-7.0可能不等于120.0-117.0(使用==),例如。@LJ2我想您的意思是,20.0-7.0!=到120.0-
107.0
?是的,数学,我不太擅长,尤其是在处理一到两位数的减法时:/Thanks@LJ2: 20. - 7.等于120107在每个常见的浮点实现中。浮点错误不仅仅是随机发生的;行为是指定的,如果您理解规范,您可以依赖该行为。@Eric:我的示例是假设的。。。我想我