从浮点小端到大端再转换回来的问题

时间:2019-04-22 16:25:52

标签: java floating-point endianness

我正在尝试编写一个保存解析器,将浮点数保存在小字节序中,但是Java在大字节序中,因此我需要在转换时转换FP并再次返回,但这确实会导致某些浮动上的不一致点号。

我尝试读取一个浮点数,转换为int位,反转int位,然后转换回浮点。

并在反向转换中将float转换为原始int位,将int位反转,然后再转换回浮点。


    public void test()
    {
        //file contents (hex) 0x85, 0x76, 0x7e, 0xbd, 0x7f, 0xd8, 0xa8, 0x3e, 0x2f, 0xcb, 0x8f, 0x3d, 0x06, 0x7c, 0x70, 0x3f
        RandomAccessFile iRAF = new RandomAccessFile(new File("input.test"), "r");
        RandomAccessFile oRAF = new RandomAccessFile(new File("output.test"), "rw");

        byte[] input = new byte[16];
        iRAF.readFully(input);

        float[] floats = new float[4];
        for (int i = 0; i < 4; i++)
        {
            floats[i] = readFloat(iRAF);
        }
        writeFloats(oRAF, floats);

        byte[] output = new byte[16];
        oRAF.seek(0);
        oRAF.readFully(output);

        if (Arrays.equals(input, output) == false)
        {
            System.err.println(toHex(input));
            System.err.println(toHex(output));
        }
    }

    private String toHex(byte[] bytes)
    {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++)
        {
            sb.append(String.format("%02x", bytes[i])).append(" ");
        }
        return sb.toString();
    }

    public float readFloat(RandomAccessFile raf) throws IOException
    {
        return Float.intBitsToFloat(Integer.reverseBytes(Float.floatToRawIntBits(raf.readFloat())));
    }

    public void writeFloats(RandomAccessFile raf, float... floats) throws IOException
    {
        for (int i = 0; i < floats.length; i++)
            raf.writeFloat(Float.intBitsToFloat(Integer.reverseBytes(Float.floatToRawIntBits(floats[i]))));
    }

我希望输出具有与输入完全相同的十六进制值:

85 76 7e bd 7f d8 a8 3e 2f cb 8f 3d 06 7c 70 3f

但实际输出是:

85 76 7e bd 7f c0 00 00 2f cb 8f 3d 06 7c 70 3f

这是由于某些浮点舍入错误而引起的,或者可能是在转换时将其转换为NaN值并且不保留位的原因(尽管我本以为这就是Float.floatToRawIntBits()的作用。

1 个答案:

答案 0 :(得分:3)

我相信您会遇到NaN崩溃的情况。如果您确实需要区分不同的NaN值,那么您将面临的不仅仅是文件存储问题。根据Java语言规范4.2.3. Floating-Point Types, Formats, and Values

  

IEEE 754为其每个单个值允许多个不同的NaN值   和双浮点格式。而每种硬件架构   生成新的NaN时,返回NaN的特定位模式,   程序员还可以创建具有不同位模式的NaN来   例如,对回顾性诊断信息进行编码。

     

在大多数情况下,Java SE平台会处理给定值的NaN值   类型,好像折叠成一个规范值,因此   规范通常指的是任意的NaN,   规范值。

我问“为什么使用Float.floatToRawIntBits(raf.readFloat())而不是raf.readInt()?”因为我试图理解并可能简化您的测试程序,而不希望解决该问题。