gpt4 book ai didi

java - Little Endian 到 Big Endian 精度误差

转载 作者:行者123 更新时间:2023-11-29 03:32:03 29 4
gpt4 key购买 nike

我正在用 Java 编写一个程序来输入一个文件,供另一个用 C++ 编写的程序使用。因此,该文件必须是 float 的小端二进制文件。

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

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

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

推荐的解决方案是将文件直接转换为 int 位,而不是进行这种循环处理。但是,就我而言,直接转换为整数会使我失去对我需要编写的原始 float 的精度。推荐的方案是,供大家引用:

"By reading a float using the readFloat() routine of DataInputStream, converting it to bits using Float.floatToIntBits(), swapping the Integer, then converting it back to float using Float.intBitsToFloat() causes a precision error in certain cases resulting in junk being returned.

The solution is to write a new set of routines that read the bits from the bytestream directly into integers, then perform the byte swapping and converting it back to a float."

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

将这一系列的 float 写入二进制文件并读回时,预期的结果是这样的:

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)))‌​. 

最佳答案

您是从输入流中获取数字,还是将它们写入输出流?目前尚不清楚您要做什么。如果您从 InputStream 读取它们,您应该只执行一行 Float.intBitsToFloat(Integer.reverseBytes(dataInputStream.readInt()))。如果您将它们写入 OutputStream,您应该只执行一行 dataOutputStream.writeInt(Integer.reverseBytes(Float.floatToRawIntBits(float)))‌ .其他一切都只是在原地打转。

关于java - Little Endian 到 Big Endian 精度误差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17683429/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com