我正在尝试实现Comparator,考虑到要比较的对象(Word
)有两个属性定义为int
。
我希望得到这两个值的标准偏差(可能更多,但现在是2),并对列表中的对象具有最低值进行排序。但显然,它是说我的方法不是基于this question的传递(我认为,因为我有相同的例外)。但我不知道如何,这里只会比较标准偏差的结果。
我是否对数学感到困惑,并没有考虑一个特殊情况,指出这种方法不是传递性的,或者我做错了什么?
对列表进行排序:
for(Map.Entry<String,List<Word>> entry: list.entrySet()){
Collections.sort(entry.getValue(), Collections.reverseOrder(new SimpleComparator()));
...
}
比较类:
import java.util.Comparator;
public class SimpleComparator implements Comparator<Word> {
@Override
public int compare(Word word1, Word word2) {
int b1,b2,f1,f2;
double average1,average2, result1,result2;
b1 = word1.getAttr1();
b2 = word2.getAttr1();
f1 = word1.getAttr2();
f2 = word2.getAttr2();
average1 = (b1-f1)/2;
average2 = (b2-f2)/2;
result1 = Math.sqrt((Math.pow(b1-average1,2)+Math.pow(f1-average1,2))/2);
result2 = Math.sqrt((Math.pow(b2-average2,2)+Math.pow(f2-average2,2))/2);
return (int)(result1 - result2);
}
}
答案 0 :(得分:3)
你应该使用Math.signum(result1 - result2)
,如果结果为负则产生-1,如果结果为零则产生0,如果结果为正则产生1。确保将结果保持为double - 将double转换为int时发生的截断会产生不准确的结果。
相反,请将您的return语句替换为:
return (int) Math.signum( result1 - result2 );
在这种情况下,0.9 - 0.3
的结果为0.6
,其结果为1
。但是,如果我们将双0.6
转换为int,则结果为0
,而不是1
,表示它们相等。但是,我们知道这不是真的。这样做的原因是,当将数值数据类型转换为较低精度之一时,该值不会舍入 - 它只会丢失精度,这意味着小数点后的值会下降。
请参阅JavaDocs Comparator.comare(T, T)
实现者必须确保所有x和y的sgn(compare(x,y))== -sgn(compare(y,x))。
答案 1 :(得分:0)
您的compare(x1,x2)
方法违反了条件:
实现者必须确保compare(x,y)== 0暗示 所有z的sgn(compare(x,z))== sgn(compare(y,z))。
以下是compare(w1,w2)=0
public static void main(String[] args) {
Word w1=new Word(2,5);
Word w2=new Word(1,5);
Word w3=new Word(2,4);
System.out.println(Math.signum(getStandardDeviation(w1, w3))==Math.signum(getStandardDeviation(w2, w3)));
}
public static double getStandardDeviation(Word word1,Word word2)
{
int b1,b2,f1,f2;
double average1,average2, result1,result2;
b1 = word1.getAttr1();
b2 = word2.getAttr1();
f1 = word1.getAttr2();
f2 = word2.getAttr2();
average1 = (b1-f1)/2;
average2 = (b2-f2)/2;
result1 = Math.sqrt((Math.pow(b1-average1,2)+Math.pow(f1-average1,2))/2);
result2 = Math.sqrt((Math.pow(b2-average2,2)+Math.pow(f2-average2,2))/2);
return (int)(result1 - result2);
}
}