Чтение 64-битного float little-endian на Java


Как я могу прочитать 64-битное значение float 1504642224.94664 из шестнадцатеричного C2 95 3C 2C C1 6B D6 41 с помощью Java? Я перепробовал все предложения, которые нашел в интернете, и, похоже, ничто не возвращает ожидаемое значение.

В настоящее время я использую Netty 4.1.24.Final для моего кода ввода-вывода, и я бы предпочел решение как таковое. Я также использую поплавки для хранения значения, но я гибок в отношении конечного типа.

ByteBuf buffer = Unpooled.copiedBuffer( IO.decodeHex( "C2953C2CC16BD641" ) );
buffer.readBytes( 8 ).order( ByteOrder.LITTLE_ENDIAN ).readFloat()

Это решение когда-то работало, но таинственным образом оно перестало работать после обновления Java и Netty - возможно, оно никогда не работало а я просто забыл. Кроме того, Нетти отвергла метод order() в пользу метода readFloatLE(), который также не работает.

Благослови Скриншот

Как вы можете видеть, я получил шестнадцатеричный редактор Bless для отображения правильного значения, поэтому должно быть решение. Бонусные очки: каким было бы обратное решение, чтобы записать это значение обратно в 64-битный float?

2 2

2 ответа:

Я считаю, что вы просто неправильно определили свое шестнадцатеричное значение и используете неправильный тип.

Это работает для меня

double source = 1504642224.94664;
ByteBuf buffer = Unpooled.copiedBuffer( Hex.decodeHex( "C0953C2CC16BD641" ) );
double dest = buffer.readBytes( 8 ).order( ByteOrder.LITTLE_ENDIAN ).readDouble();

assert Double.compare(source, dest) == 0;

Вы можете попробовать это, сделав:

ByteBuf hex = Unpooled.buffer(8).order(ByteOrder.LITTLE_ENDIAN);
hex.writeLong(Double.doubleToLongBits(1504642224.94664));
System.out.println(ByteBufUtil.prettyHexDump(hex));

Который дает C0 95 3C 2C C1 6B D6 41.

Я думаю, что вы должны учитывать тот факт, что вы хотите прочитать double, но Вы читаете его как float, поэтому используются только 4 байта, так как в Java a float - это 4 байта.

Вы должны сделать это вместо:

 ByteBuffer buf = ByteBuffer.wrap(new byte[] { (byte)0xC2, (byte)0x95, 0x3C, 0x2C, (byte)0xC1, 0x6B, (byte)0xD6, 0x41 });
 double d = buf.order(ByteOrder.LITTLE_ENDIAN).getDouble();
 System.out.printf("%f", d);

Мое решение заключается в использовании JDK native ByteBuffer, но я вижу, что также ByteBuf имеет

getDouble(int index) Возвращает 64-разрядное число с плавающей запятой в указанном абсолютном индексе в этом буфере.