背景:浮点数具有舍入问题,因此不应将它们与“==”进行比较.
问题:在Java中,如何测试Double列表是否包含特定值.我知道各种解决方法,但我正在寻找最优雅的解决方案,可能是使用Java或第三方库功能的解决方案.
import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { // should be 1.38,but end up with 1.3800000000000001 Double d1 = new Double(1.37 + 0.01); System.out.println("d1=" + d1); // won't be able to test the element for containment List<Double> list = new ArrayList<Double>(); list.add(d1); System.out.println(list.contains(1.38)); } }
输出是:
d1=1.3800000000000001 false
谢谢.
解决方法
一般的解决方案是编写一个循环遍历列表的实用程序方法,并检查每个元素是否在目标值的某个阈值内.不过,使用
Stream#anyMatch()
,我们可以在Java 8中做得更好:
list.stream().anyMatch(d -> (Math.abs(d/d1 - 1) < threshold))
请注意,我使用了建议here的相等测试.
如果你不使用Java 8,我会写一个简单的实用工具方法:
public static boolean contains(Collection<Double> collection,double key) { for (double d : collection) { if (Math.abs(d/key - 1) < threshold) return true; } return false; }
请注意,您可能需要为这两种方法添加一个特殊情况,以检查列表是否包含0(或使用abs(x-y)< eps方法).那只是添加|| (abs(x)< eps&& abs(y)< eps)到相等条件的结束.