Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么要使用Double.doubleToLongBits()而不是强制转换?_Java - Fatal编程技术网

Java 为什么要使用Double.doubleToLongBits()而不是强制转换?

Java 为什么要使用Double.doubleToLongBits()而不是强制转换?,java,Java,编辑: 我想我的目的不被理解,所以投了反对票和评论。我不想知道浮点double的哪个位意味着什么,也不想知道它们是否在长时间内匹配相同的位置;这与我完全无关。我的问题如下:我想使用一个基元数组来存储我的所有基元值。如果我选择一个double[]作为存储,我也需要能够在其中存储long,我也可以用另一种方式,但问题不会消失,只是会被逆转。既然两个都是相同的大小,它应该会起作用。使用Double.Double或awlongbits双精度和Double.longbits到doubleLong允许我这样

编辑:

我想我的目的不被理解,所以投了反对票和评论。我不想知道浮点double的哪个位意味着什么,也不想知道它们是否在长时间内匹配相同的位置;这与我完全无关。我的问题如下:我想使用一个基元数组来存储我的所有基元值。如果我选择一个double[]作为存储,我也需要能够在其中存储long,我也可以用另一种方式,但问题不会消失,只是会被逆转。既然两个都是相同的大小,它应该会起作用。使用Double.Double或awlongbits双精度和Double.longbits到doubleLong允许我这样做。但我想知道的是:我能不能把一个长发换成一个双发和一个后发,然后总是得到同样的长发?如果这是真的,那么它就解决了我的问题,我不在乎这些比特是否在内部移动。所以我想测试一下我是否能安全地做到这一点。输出表示所有64位都可以单独访问和修改,但这可能不足以证明没有长位丢失/修改

我刚刚发现,通过一个小测试,我可以正确地处理双精度中的每一位,只需将其转换为long和back。以下是至少在Java 7/Windows 7 64位上成功的测试程序:

import static org.junit.Assert.assertTrue;
import org.junit.Test;

public class TestDoubleBits {
    private static double set(final double d, final int bit, final boolean value) {
        if (value) {
            return ((long) d) | (1L << bit);
        } else {
            return ((long) d) & ~(1L << bit);
        }
    }

    private static boolean get(final double d, final int bit) {
        return (((long) d) & (1L << bit)) != 0;
    }

    @Test
    public void testDoubleBits() {
        final double value = Math.random();
        for (int bit = 0; bit < 64; bit++) {
            assertTrue((get(set(value, bit, false), bit) == false));
            assertTrue((get(set(value, bit, true), bit) == true));
        }
    }
}

由于本机方法通常较慢,因此方法的内容可能较快,但本机调用的开销使其较慢,使用这些方法有什么好处吗?

浮点数的位模式永远不会与相应整数值的位模式(如果存在)有一点类似

我建议您运行以下程序

public class Test
{
    public static void main(String[] args) {
        double d = 1.3;
        long d1 = (long) d;
        long d2 = (Double.doubleToLongBits(d));
        System.out.printf("cast %016X bits %016X\n", d1, d2);
    }
}
然后读

当然,例外情况是值为零

如果你想进一步调查,纽约城市大学有一个简洁的交互界面,显示你想知道的关于任何给定数字的浮点表示的所有信息。

这是我应该使用的测试。它在53处失败,我假设这意味着只有long的前52位可以安全地存储在double中,而不使用那些本机方法,这也排除了使用任何负值

public class TestDoubleBits {
    public static void main(final String[] args) {
        int failsAt = -1;
        long value = 1;
        for (int bit = 1; bit < 64; bit++) {
            value = value | (1L << bit);
            final double d = value;
            final long l2 = (long) d;
            if (value != l2) {
                failsAt = bit;
                break;
            }
        }
        System.out.println("failsAt: " + failsAt);
        value = value & ~(1L << failsAt);
        System.out.println("Max value decimal: " + value);
        System.out.println("Max value hex:     " + Long.toHexString(value));
        System.out.println("Max value binary:  " + Long.toBinaryString(value));
    }
}

我最初测试的问题是,我单独测试了这些位。通过始终将第一位设置为1,我可以知道何时开始丢失数据,因为最低有效位是第一个丢失的位。

您的测试程序无法证明这一点,因为它可以操纵通过铸造双精度的长度。但是,这种铸造实际上改变了钻头;所以你根本就不能访问double的位。实际上,获得一个随机双精度,然后在使用它时将其转换为long与获得随机long非常相似,只是分布不同。@DavidWallace我对访问双精度的位一点都不感兴趣。请看一看我在问题中写的附加信息。好吧,这是一个完全不同的问题,答案是否定的。请看我在Jim答案下的评论。即使是整数值的双精度运算也不会有与它们的长等价项相同的位。当然,这是程序演示的内容。但是,我们可以从记忆双到长的截断中看出一个先验,所以即使我们认为位模式相似,我们也可以看到信息必须丢失。不过,我会澄清答案。哦,从来都不是一个危险的词。至少有一个double的表示形式与long等价物的表示形式相同。好吧,我给你一个:-将long转换为double和back并不总是得到相同的long,因为有些long值不能用double精确表示。这就是你要问的吗?还不完全清楚。
public class TestDoubleBits {
    public static void main(final String[] args) {
        int failsAt = -1;
        long value = 1;
        for (int bit = 1; bit < 64; bit++) {
            value = value | (1L << bit);
            final double d = value;
            final long l2 = (long) d;
            if (value != l2) {
                failsAt = bit;
                break;
            }
        }
        System.out.println("failsAt: " + failsAt);
        value = value & ~(1L << failsAt);
        System.out.println("Max value decimal: " + value);
        System.out.println("Max value hex:     " + Long.toHexString(value));
        System.out.println("Max value binary:  " + Long.toBinaryString(value));
    }
}