Java 哪个双精度值与自身的比较最快?

Java 哪个双精度值与自身的比较最快?,java,optimization,Java,Optimization,把我的问题放在上下文中:我有一个类,它根据每个元素的计算分数在构造函数中对列表进行排序。现在我想将我的代码扩展到一个不排序列表的类版本。最简单的解决方案(但显然不是干净的,我完全知道,但时间紧迫,我现在没有时间重构代码)是使用一个分数计算器,为每个元素分配相同的分数 我应该选择哪个双精度值?我个人认为+无穷大或-无穷大,因为我假设它们有一个特殊的表示,这意味着它们可以很快进行比较。这是正确的假设吗?我对java的底层实现知之甚少,无法判断我是否正确。不确定这是否合适,但您是否考虑过编写自己的版本

把我的问题放在上下文中:我有一个类,它根据每个元素的计算分数在构造函数中对列表进行排序。现在我想将我的代码扩展到一个不排序列表的类版本。最简单的解决方案(但显然不是干净的,我完全知道,但时间紧迫,我现在没有时间重构代码)是使用一个分数计算器,为每个元素分配相同的分数


我应该选择哪个双精度值?我个人认为+无穷大或-无穷大,因为我假设它们有一个特殊的表示,这意味着它们可以很快进行比较。这是正确的假设吗?我对java的底层实现知之甚少,无法判断我是否正确。

不确定这是否合适,但您是否考虑过编写自己的版本

看起来有点担心的是,您正在寻找一个具有特定性能特性的对象,而这些特性不可能始终出现在一般实现中。即使你通过实验或者源代码找到了一个完美的候选人,你也不能保证合同的有效性

static class ConstDouble extends Number implements Comparable<Number> {

    private final Double d;
    private final int intValue;
    private final long longValue;
    private final float floatValue;

    public ConstDouble(Double d) {
        this.d = d;
        this.intValue = d.intValue();
        this.longValue = d.longValue();
        this.floatValue = d.floatValue();
    }

    public ConstDouble(long i) {
        this((double) i);
    }

    // Implement Number
    @Override
    public int intValue() {
        return intValue;
    }

    @Override
    public long longValue() {
        return longValue;
    }

    @Override
    public float floatValue() {
        return floatValue;
    }

    @Override
    public double doubleValue() {
        return d;
    }

    // Implement Comparable<Number> fast.
    @Override
    public int compareTo(Number o) {
        // Core requirement - comparing with myself will always be fastest.
        if (o == this) {
            return 0;
        }
        return Double.compare(d, o.doubleValue());
    }

}
// Special constant to use appropriately.
public static final ConstDouble ZERO = new ConstDouble(0);

public void test() {
    // Will use ordinary compare.
    int d1 = new ConstDouble(0).compareTo(new Double(0));
    // Will use fast compare.
    int d2 = ZERO.compareTo(new Double(0));
    // Guaranteed to return 0 in the shortest time.
    int d3 = ZERO.compareTo(ZERO);
}
静态类ConstDouble扩展了可比较的{
私人决赛双d;
私人最终int值;
私人最终长期价值;
私人最终浮动价值;
公共交通(双d){
这个。d=d;
this.intValue=d.intValue();
this.longValue=d.longValue();
this.floatValue=d.floatValue();
}
公共交通(长一){
这个((双)i);
}
//机具编号
@凌驾
公共int值(){
返回值;
}
@凌驾
公共长期价值(){
返回长值;
}
@凌驾
公共浮动价值(){
返回浮点值;
}
@凌驾
公共双双值(){
返回d;
}
//实现速度相当快。
@凌驾
公共整数比较(数字o){
//核心要求-与自己相比,永远是最快的。
如果(o==这个){
返回0;
}
返回Double.compare(d,o.doubleValue());
}
}
//要适当使用的特殊常数。
公共静态最终ConstDouble零=新ConstDouble(0);
公开无效测试(){
//将使用普通比较。
int d1=新的双精度常数(0)。与(新的双精度常数(0))相比;
//将使用快速比较。
int d2=零。比较(新的双精度(0));
//保证在最短时间内返回0。
int d3=零。与(零)相比;
}

显然,您需要在收藏中使用
compariable
而不是
Double
,但这可能不是一件坏事。您可能可以设计一种机制来确保始终优先使用快速通道比较(取决于您的使用)。

通常避免
0.0
-0.0
NaN
。任何其他号码都可以。您可以查看实施情况,以确定它们是专门处理的:

if (d1 < d2)
    return -1;           // Neither val is NaN, thisVal is smaller
if (d1 > d2)
    return 1;            // Neither val is NaN, thisVal is larger

// Cannot use doubleToRawLongBits because of possibility of NaNs.
long thisBits    = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);

return (thisBits == anotherBits ?  0 : // Values are equal
        (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
         1));                          // (0.0, -0.0) or (NaN, !NaN)
if(d1d2)
返回1;//两个val都不是NaN,这个val更大
//由于可能出现NAN,无法使用doubleToRawLongBits。
长位=Double.Double到长位(d1);
长另一位=双。双到长位(d2);
返回(thisBits==其他位?0://值相等
(此位<其他位?-1://(-0.0,0.0)或(!NaN,NaN)
1));                          // (0.0,-0.0)或(NaN,!NaN)
然而,这取决于排序比较器的实现方式。如果你不使用Double.compare,那么这可能并不重要


请注意,除了这些特殊情况外,
0.0/-0.0/NaN
双数比较是在CPU内部进行的,而且速度非常快,因此与您已有的其他代码相比,您不太可能获得任何显著的比较开销。

其中一个,或者如果对您有效,则为零,或者可能为NaN。@EJP您能详细说明一下吗?只是因为它们是常数吗?我假设Double.compareTo函数看起来是一点一点的,所以可能每个值都是可以接受的。不过,我想知道一个推理。是的,这是因为它们有固定的表示形式,不需要预先定标。我刚刚运行了一个测试程序,对常量或随机双精度值进行了一百万次比较。对于所有情况,我都无法测量可记录的运行时(<10ms)。无限比较是最快的(根本没有可测量的运行时)。与
Double
相比,这个类的优势是什么?@RobinKrahl-您不仅可以保证常量比较(例如我的示例中的
ZERO
一个比较)在最短的时间内检测平等性,但他们将通过对JVM的更改继续这样做。@RobinKrahl-进一步的修补建议使用
Comparable
-可能更好。编号的其他替代方法。与相比。