Java 稳健地图<;双倍;在爪哇
我正在寻找Java中的健壮映射,其中键查找将考虑Double具有有限的精度(大约1e-15或1e-16)。我在哪里能找到这样的东西Java 稳健地图<;双倍;在爪哇,java,collections,Java,Collections,我正在寻找Java中的健壮映射,其中键查找将考虑Double具有有限的精度(大约1e-15或1e-16)。我在哪里能找到这样的东西 编辑:按照Jon的建议,我认为定义等价性是有意义的。一个想法是将这些数字集中在四舍五入到15个最相关的十进制数字。其他数字将四舍五入(以任何一致的方式-最快实现)。这有意义吗?最好的实现方式是什么 我建议您使用TreeMap并实现您自己的自定义比较器,该比较器在考虑到所需精度的情况下比较两个双精度值。我不完全确定您需要它做什么,但您可以实现一个围绕双精度的包装器,并
编辑:按照Jon的建议,我认为定义等价性是有意义的。一个想法是将这些数字集中在四舍五入到15个最相关的十进制数字。其他数字将四舍五入(以任何一致的方式-最快实现)。这有意义吗?最好的实现方式是什么 我建议您使用TreeMap并实现您自己的自定义比较器,该比较器在考虑到所需精度的情况下比较两个双精度值。我不完全确定您需要它做什么,但您可以实现一个围绕双精度的包装器,并覆盖其
hashCode()
和equals()
方法以满足您的需要“有限精度”查找。因此,任何映射实现都是健壮的,因为它依赖于hashCode()
和equals()
进行键查找
当然,您的地图将采用
map
格式,最好的方法是在添加或查找值之前对值进行标准化。例如,使用舍入
顺便说一句:您可以使用支持自定义哈希策略并使用原语双键的TDoubleObjectHashMap。总结上面的答案和评论,我最终得到了以下包装器(可能不处理NaN atm):
公共静态类DoubleWrapper{
专用静态最终整数精度=15;
私人最终双舍入值;
公共DoubleWrapper(双值){
最终双d=Math.ceil(Math.log10(值<0?-value:value));
最终整数幂=精度-(整数)d;
最终双倍震级=数学功率(10,功率);
最终长位移=数学四舍五入(值*量级);
舍入值=移位/幅度;
}
公共双精度getDouble(){
返回舍入值;
}
@凌驾
公共布尔等于(对象obj){
返回roundedValue.equals(obj);
}
@凌驾
公共int hashCode(){
返回roundedValue.hashCode();
}
}
double键?真的吗?你的需求需要更精确。特别是,如果你在寻找类似“近似等价”的东西“这最终很棘手,因为地图假定如果A和B相等,B和C相等,那么A和C也必须相等。”。这对近似等价不起作用。通过“鲁棒性”,我想你希望将1e-15范围内的两个键或每一个左右的键视为同一个键?@Jon:我认为这叫做传递性(等价关系)。存储在排序列表中并使用二进制搜索如何?我如何知道我的哪个双键是“接近”的如果不将其与映射中已存在的每个双精度进行比较,则hashCode()函数应为所有“接近”的双精度返回相同的哈希代码。对于那些“接近”的双打,equals()也应该为true。无需比较地图中的所有双精度。毫无疑问,这是可以的,但由于Jon Skeet和Mitch Wheat在评论中指出的及物性属性,这并不像看上去那么容易。别忘了迎合NaN
!“闭合”-可以通过将双域拆分为多个存储单元(例如,[1.1,1.2)=1.1、[1.2,1.3)=1.2等,当然,精度需要)。
public static class DoubleWrapper {
private static final int PRECISION = 15;
private final Double roundedValue;
public DoubleWrapper(double value) {
final double d = Math.ceil(Math.log10(value < 0 ? -value: value));
final int power = PRECISION - (int) d;
final double magnitude = Math.pow(10, power);
final long shifted = Math.round(value*magnitude);
roundedValue = shifted/magnitude;
}
public double getDouble() {
return roundedValue;
}
@Override
public boolean equals(Object obj) {
return roundedValue.equals(obj);
}
@Override
public int hashCode() {
return roundedValue.hashCode();
}
}