1

我正在用 Java 编写一个程序来输入一个文件,供其他用 C++ 编写的程序使用。因此,这个文件必须是浮点数的小端二进制文件。

我使用了许多不同类型的方法来进行这种字节序转换,包括 Apache Commons I/O、Geosoft 实用程序(与 apache.. 完全相同)和 ByteBuffer。

总之,我必须采用一堆浮点数并以二进制小端显示它们。这个过程大部分时间都有效。但是,在某些情况下,在浮点数被识别为 NaN 的字节序转换中似乎存在一些精度错误。结果,当我读取我刚刚编写的大约 1% 的时间的二进制文件时,显示的不是特定的浮点数,而是 6.055E-41 之类的数字。我在网上搜索过类似的问题。

另一个人诊断出错误包含在 float 到 Int Bits 和 Int Bits 到 float 之间的转换(在 Apache 和 Geosoft Utilities 中找到)。

推荐的解决方案是将文件直接制作成 int 位,而不是进行这一轮处理。但是,在我的情况下,直接转换为整数会使我在需要编写的原始浮点数上失去精度。推荐的解决方案是,供您参考:

“通过使用 DataInputStream 的 readFloat() 例程读取浮点数,使用 Float.floatToIntBits() 将其转换为位,交换整数,然后使用 Float.intBitsToFloat() 将其转换回浮点数,在某些情况下会导致精度错误,从而导致垃圾被退回。

解决方案是编写一组新的例程,将字节流中的位直接读取为整数,然后执行字节交换并将其转换回浮点数。”

这是一个问题的例子......

将这一系列浮点数写入二进制文件并读回它们时,预期的结果是:

1.50411975 -1.974895 1.0301249 -0.43540177 0.8161005 0.38000694 0.43332508

但是,我看到了这个:

6.9055E-41 -1.974895 1.0301249 -0.43540177 0.8161005 0.38000694 0.43332508

我正在粘贴我的代码。此版本专门使用字节缓冲区实现。你能告诉我什么是错的,我该如何解决它?

public int writeBinaryFile( ArrayList<P> p) throws FileNotFoundException, IOException 
{ 
    int c = 0;


    for (int i = 0; i < p(); i++)
    {
        ArrayList<Float> cube = new ArrayList<Float>();
        ArrayList<Float> dir = p.get(i).getDirection();
        ArrayList<Float> pos = p.get(i).getPosition();
        Float angle = (float) p.get(i).getAngle();
        Float id = (float) p.get(i).getPEvents().get(0).getid();
        ArrayList<Float> things = new ArrayList<Float>();
        boolean truism = true;


    if (dir.get(1) > 0 ) {  

        /*byte [] byte2 = this.float2ByteArray(id);
        float f = ByteBuffer.wrap(byte2).order(ByteOrder.LITTLE_ENDIAN ).getFloat();
        dos.writeFloat(f);*/

        for (int j = 0; j < pos.size(); j++) {
            byte [] bytes = this.float2ByteArray(pos.get(j));
            float d = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN ).getFloat();
            cube.add(d);
        }

        for (int j = 0; j < dir.size(); j++) {
            byte [] bytes = this.float2ByteArray(dir.get(j));
            float d = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN ).getFloat();
            cube.add(d);
        }

        byte [] bytes = this.float2ByteArray(angle);
        float d = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN ).getFloat();
        cube.add(d);

        if (this.checkCube(cube)) {this.writeCube(cube); c++; }

    }

    }
    return c;
}

    public byte [] float2ByteArray(float value)
{
    return ByteBuffer.allocate(4).putFloat(value).array();
}

这是我拥有的备用交换机制:

 public static float swap (float value)
  {
    int intValue = Float.floatToRawIntBits (value);
    intValue = swap (intValue);
    return Float.intBitsToFloat (intValue);
  }

 public static int swap (int value)
  {
    int b1 = (value >>  0) & 0xff;
    int b2 = (value >>  8) & 0xff;
    int b3 = (value >> 16) & 0xff;
    int b4 = (value >> 24) & 0xff;
    return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0;
  }

我尝试使用直接使用整数的东西。这是我的特殊交换器:

 public static float specialswap (float value)
 {
     int intValue = Float.floatToRawIntBits (value);
     return Integer.reverseBytes(Integer.parseInt(Integer.toBinaryString(intValue)));

}

已解决:感谢 Louis Wasserman,找到了我的问题的答案:

dataOutputStream.writeInt(Integer.reverseBytes(Float.floatToRawIntBits(float)))‌​. 
4

1 回答 1

4
于 2013-07-22T19:04:06.630 回答