是否可以设置Set的精度 。载有()?

问题描述 投票:8回答:4

假设我们有Set<Double>的实现。它包含以下值:[2.0, 5.0, 7.0]

在这种情况下,contains(2.0001d)返回false,因为double值通过完全匹配进行比较。

是否可以为boolean contains(Object o)方法设置一些双精度?

如果不可能,除了在顺序集合中存储值,迭代它并比较每个值之外,您可以建议哪种解决方法?

java set double precision
4个回答
3
投票

可能你可以使用Sun's answer,例如,基于anyMatch之后的前两位数进行比较:

.

2
投票

我可以看到三个选项:

  • 在将数字添加到集合之前对数字进行舍入
  • 写一个Set<Double> set = Set.of(2.0, 5.0, 7.0); Double compared = 2.0001d; System.out.println( set.stream().anyMatch(aDouble -> Math.floor(aDouble * 100) / 100 == Math.floor(compared * 100) / 100 )); 包装类并重新定义equals方法
  • 使用double和自定义比较器

请注意,最后两个选项可能会或可能不会令人满意,因为填充集合的顺序会影响保留哪些元素。例如,如果将精度设置为0.01并添加0.01然后加上0.011然后加上0.02,则集合中将包含两个元素(0.01和0.02)。如果你加0.011然后0.01然后加0.02,你将只有一个元素:0.011。我不知道这对你的用例是否有问题。

最后一个选项可能如下所示:

TreeSet

使用示例:

static Set<Double> setWithPrecision(double epsilon) {
  return new TreeSet<> ((d1, d2) -> {
    if (d1 <= d2 - epsilon) return -1;
    if (d1 >= d2 + epsilon) return 1;
    return 0;
  });
}

0
投票

假设你的Set<Double> set = setWithPrecision(0.01); set.add(0d); set.add(0.00001d); set.add(0.01d); set.add(0.02d); System.out.println(set); // [0.0, 0.01, 0.02] 调用点在一个方法中,某种方式从某个地方接收到HashSet#contains,你可以简单地继续并设置Double的精度。虽然Double没有提供圆形Double对象的开箱即用的方法,但你可以很好地创建一个舍入助手,它将接受你想要达到的精度并返回舍入的数字。

例如:

Double

通过public static Double roundToPrecision(Double number, int precision) { return BigDecimal.valueOf(number) .setScale(precision, RoundingMode.DOWN) .doubleValue(); } 将有效地导致这回到2.0001d

© www.soinside.com 2019 - 2024. All rights reserved.