Чтение 64-разрядного числа с плавающей точкой в ​​Java - PullRequest
0 голосов
/ 30 мая 2018

Как я могу прочитать 64-битное значение с плавающей запятой 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 Screenshot

Как вы можете видеть;Я заставил Bless Hex Editor отображать правильное значение, поэтому должно быть решение.Бонусные баллы: Каково было бы обратное решение записать это значение обратно в 64-битное число с плавающей запятой?

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

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

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

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.

0 голосов
/ 30 мая 2018

Я думаю, вы должны учитывать тот факт, что вы хотите прочитать double, но вы читаете его как float, поэтому используются только 4 байта, поскольку в Java 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-разрядное число с плавающей запятой по указанному абсолютному индексу в этом буфере.

...