我很难理解这个错误背后的逻辑,所以我有一个比较方法:
public int compareTo(osobnik obj) {
if (this.fitness == -1 && obj.fitness==-1)
return 0;
if (this.fitness == -1)
return 1;
if (obj.fitness == -1)
return -1;
if (this.fitness > obj.fitness)
return 1;
if (this.fitness < obj.fitness)
return -1;
return 0;
}
直到fittnes被计算为1/(x^5 + x^4+3x^2+x-5)的绝对值,一切都很好(有一个问题,如果分母的值为0,那么fittnes是-1)。但如果我将函数更改为 1/(x^5 + x^4-3x^2+x-5) (作为 3x^2 旁边的符号更改),我会得到“比较方法违反了其一般契约”。为什么?为什么它对一组数字有效而对第二组数字无效?
<小时/>[已解决]
事实证明,比较功能是正确的。罪犯隐藏在 1/x 中,转向 NaN。
最佳答案
域 <0,100>
的适应度函数范围包括您的特殊情况值 -1。这可能不是您眼前的问题,但绝对是一个问题。如果你想支持“不适合”的情况,请使用 -Double.MAX_VALUE
或Double.NEGATIVE_INFINITY
。那么您的比较函数中就不需要特殊情况了。复杂的比较逻辑通常最终会破坏自反性、对称性和传递性的基本属性之一,当这些属性被破坏时,排序算法就会崩溃,但您已经看到了异常(exception)。
按照上面整理的特殊情况,执行 compareTo
简单地就像
return Double.compare(this.fitness, obj.fitness);
(假设 fitness
是 double
)。
此外,您选择的适应度函数值得怀疑,因为:
- 在
x = 1
附近有一个奇点最糟糕的一种,左边界和右边界极端相反; - 它很快就接近于零
x > 2
,因此对于该范围来说不是一个好的判别器。
关于java - "Comparison method violates its general contract"当我改变计算方法时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23129754/