Java,双精度数组及其索引的排序数组



我在这个论坛和其他论坛上读了很多关于这个问题的文章,但我仍然无法得到具体的答案。无论如何,我决定这样做:

下面是一个保存字符串和整数的类:

public class Tuple{
    private String token;
    private int docID;

    public Tuple(String token, int docID) {
        this.token = token;
        this.docID = docID;
    }
    public String getToken() {
        return token;
    }
    public void setToken(String token) {
        this.token = token;
    }
    public int getDocID() {
        return docID;
    }
    public void setDocID(int docID) {
        this.docID = docID;
    }
}

然后,我创建一个数组列表来将这些元组放在private ArrayList<Tuple> temps = new ArrayList<>();

然后我像这样填充数组列表:

for ( int i = 0; i < numberOfDocs; i++ )
{
    Tuple cat = new Tuple(Double.toString(vect[i]),i);
    temps.add(cat);
}

最终,我将像这样对数组进行排序:

public void sortTmp() 
{
    Collections.sort(temps, new Comparator<Tuple>() 
    {
        @Override
        public int compare(Tuple tr2, Tuple tr1)
        {
            return tr2.getToken().compareTo(tr1.getToken());
        }
    });
}

java 和双精度存在一些问题,我不能直接使用我的双矩阵,所以我必须做Double.toString().结果已排序,但不完全正确,因为从双精度数排序计算的字符串不是很准确。

有什么想法吗?

如果你通过String表示来比较double的字典顺序,你确实可能会发现一些意想不到的结果。

您可以:

  • 重构Tuple,以便tokendouble(如果要在实例上调用compareTo,则Double包装器(
  • 否则,在 Comparator 中,您可以在 String 上调用 Double.parseDouble(这应该是相对安全的,因为 String 首先来自 double s(,并在返回的 Double 包装器上调用compareTo

最后一个选项听起来很丑陋,因为您在DoubleString之间有一堆看似不必要的来回转换,反之亦然。

这也意味着性能下降,因为在对集合进行排序时,compareTo将被多次调用。

您可以在Tuple中将令牌存储为双精度,并实现Comparable接口。 在getToken中,您可以返回实际需要的双精度形式的字符串表示。

public class Tuple implements Comparable<Tuple>{
    private double token;
    private int docID;
    public Tuple(double token, int docID) {
        this.token = token;
        this.docID = docID;
    }
    public String getToken() {
        return String.valueOf(token);
    }
    public void setToken(double token) {
        this.token = token;
    }
    public int getDocID() {
        return docID;
    }
    public void setDocID(int docID) {
        this.docID = docID;
    }
    @Override
    public int compareTo(Tuple o) {
        return Double.compare(this.token, o.token);
    }
}

如果真的需要将双精度转换为字符串,使用起来更安全

BigDecimal.valueOf(vect[i])).toString(); 

因为它处理双重不可预测性。

我和弗拉德·博切宁有同样的想法:

您只需实现Comparable并覆盖compareTo

public class Tuple implements Comparable<Tuple> {
    public Double token;
    public int docID;
    public Tuple(final double token, final int docID) {
        this.token = token;
        this.docID = docID;
    }
    @Override
    public int compareTo(final Tuple o) {
        return this.token.compareTo(o.token);
    }
}

还有一个单元测试:

public class TestTuple {
    @Test
    public void testSort() {
        final Random r = new Random(System.currentTimeMillis());
        final int numberOfDocs = 100;
        final ArrayList<Tuple> temp = new ArrayList<Tuple>();
        for (int i = 0; i < numberOfDocs; i++) {
            temp.add(new Tuple(r.nextDouble(), i));
        }
        Collections.sort(temp);
        Tuple old = temp.get(0);
        // test if sorted
        for (final Tuple next : temp) {
            Assert.assertTrue(next.token >= old.token);
            old = next;
        }
    }
}

您可以将令牌存储为元组中的双精度,并实现可比较接口。 在getToken中,您可以以实际需要的形式返回双精度的字符串表示。

private double token;
private int docID;
public Tuple(double token, int docID) {
    this.token = token;
    this.docID = docID;
}
public String getToken() {
    return String.valueOf(token);
}
public void setToken(double token) {
    this.token = token;
}
public int getDocID() {
    return docID;
}
public void setDocID(int docID) {
    this.docID = docID;
}
@Override
public int compareTo(Tuple o) {
    return Double.compare(this.token, o.token);
}

}

查看有关比较的更多信息

最新更新