繁体   English   中英

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

[英]Why use Double.doubleToLongBits() instead of casting?

编辑:

我认为我的目的没有被理解,因此投了反对票和评论。 我对知道浮点数(双精度数)的含义以及它们是否长时间匹配相同位置不感兴趣; 这与我完全无关。 我的问题如下:我想使用一个原始数组存储所有原始值。 如果我选择double []作为“存储”,我还需要能够在其中存储多头(我也可以用其他方法来做,但是问题不会消失,只是可以逆转)。 由于两者的大小相同,因此应该可以正常工作。 使用Double.doubleToRawLongBits(double)和Double.longBitsToDouble(long)可以做到这一点。 但是我想知道的是:“我可以只将一首长乐投向双打并退回,并始终获得相同的长投回吗?” 如果那是真的,那么它解决了我的问题,而且我也不在乎这些钻头是否在内部移动。 所以我想测试我是否可以安全地做到这一点。 输出显示所有64位都可以单独访问和修改,但这可能不足以证明没有长位丢失/修改。

我刚刚进行了一次小测试,发现我可以正确地“寻址”成双倍的每一位,只需将其长短地放回去即可。 这里是测试程序(至少在Java 7 / Windows 7 64bit上成功):

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));
        }
    }
}

假设我的测试程序正确地“证明”了可以通过双击long和back来访问double的每一位,为什么我们具有以下本机方法:

Double.doubleToRawLongBits(double)
Double.longBitsToDouble(long)

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

如果存在浮点数的位模式,则永远不会(除非一个例外)与相应整数值的位模式相似。

我建议您运行以下程序

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);
    }
}

然后阅读每位计算机科学家应该了解的有关浮点运算的知识

(当然,例外是零值)

如果您想进一步研究,CUNY有一个简洁的交互式浮点转换器 ,其中显示了您想要了解的任何给定数字的浮点表示形式的所有信息。

这是我应该使用的测试。 它在53处失败,这(我假设)意味着,在不使用那些本机方法的情况下,只能将long的前52位“安全”存储在双精度中(这也排除了使用任何负值)。

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,我可以找出何时开始丢失数据 ,因为最低有效位是“第一位”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM