Я использовал информацию с сайта , на которую указал Эндрю Мортон в комментариях. В основном, сохраненное 16-разрядное количество состоит из 15-разрядного целого числа с дополнительным двоичным числом (когда lsb равно 0) или 12-разрядного целого числа с дополнительным двоичным числом плюс код обработки, указывающий масштабный коэффициент, который должен быть применен к этому целому числу (когда lsb это 1). Я не знаком с vb.net, поэтому предоставляю код ISO-C здесь. Программа ниже успешно декодирует все данные, представленные в вопросе.
Примечание. Я выполняю преобразование в 8-байтовый double
в приведенном ниже коде, хотя вопрос предполагает, что первоначальное преобразование могло быть в 10-байтовом формате long double
(80-битный формат расширенной точности математический сопроцессор 8087). Казалось бы, неплохо попробовать больше тестовых данных для достижения полного охвата восьми кодов масштабирования: большие целые числа, такие как 1 000 000 и 1 000 000 000; десятичные дроби, такие как 0,0003, 0,000005 и 0,00000007; и бинарные фракции, такие как 0,125 (1/8) и 0,046875 (3/64).
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct {
uint8_t byte1;
uint8_t byte2;
} num;
num data[] =
{
{ 7, 241}, {254, 255}, { 9, 156}, { 9, 181}, { 9, 206}, { 9, 231},
{ 13, 0}, {137, 12}, { 9, 25}, {137, 37}, { 9, 50}, { 15, 2},
{ 9, 75}, {137, 87}, { 9, 100}, {137, 112}, { 2, 0}, {199, 13},
{ 7, 15}, { 71, 16}, {135, 17}, { 15, 6}, { 7, 20}, { 71, 21},
{135, 22}, {199, 23}, { 4, 0}
};
int data_count = sizeof (data) / sizeof (data[0]);
/* define operators that may look more familiar to vb.net programmers */
#define XOR ^
#define MOD %
int main (void)
{
int i;
uint8_t b1, b2;
uint16_t h, code;
int32_t n;
double r;
for (i = 0; i < data_count; i++) {
b1 = data[i].byte1;
b2 = data[i].byte2;
/* data word */
h = ((uint16_t)b2 * 256) + b1;
/* h<0>=1 indicates stored integer needs to be scaled */
if ((h MOD 2) == 1) {
/* extract scaling code in h<3:1> */
code = (h / 2) MOD 8;
/* scaled 12-bit integer in h<15:4>. Extract, sign-extend to 32 bits */
n = (int32_t)((((uint32_t)h / 16) XOR 2048) - 2048);
/* convert integer to floating-point */
r = (double)n;
/* scale based on scaling code */
switch (code) {
case 0x0: r = r * 5000; break;
case 0x1: r = r * 500; break;
case 0x2: r = r / 20; break;
case 0x3: r = r / 200; break;
case 0x4: r = r / 2000; break;
case 0x5: r = r / 20000; break;
case 0x6: r = r / 16; break;
case 0x7: r = r / 64; break;
};
} else {
/* unscaled 15-bit integer in h<15:1>. Extract, sign extend to 32 bits */
n = (int32_t)((((uint32_t)h / 2) XOR 16384) - 16384);
/* convert integer to floating-point */
r = (double)n;
}
printf ("[%3d,%3d] n=%08x r=% 12.8f\n", b1, b2, n, r);
}
return EXIT_SUCCESS;
}
Вывод этой программы следующий:
[ 7,241] n=ffffff10 r= -1.20000000
[254,255] n=ffffffff r= -1.00000000
[ 9,156] n=fffff9c0 r= -0.80000000
[ 9,181] n=fffffb50 r= -0.60000000
[ 9,206] n=fffffce0 r= -0.40000000
[ 9,231] n=fffffe70 r= -0.20000000
[ 13, 0] n=00000000 r= 0.00000000
[137, 12] n=000000c8 r= 0.10000000
[ 9, 25] n=00000190 r= 0.20000000
[137, 37] n=00000258 r= 0.30000000
[ 9, 50] n=00000320 r= 0.40000000
[ 15, 2] n=00000020 r= 0.50000000
[ 9, 75] n=000004b0 r= 0.60000000
[137, 87] n=00000578 r= 0.70000000
[ 9,100] n=00000640 r= 0.80000000
[137,112] n=00000708 r= 0.90000000
[ 2, 0] n=00000001 r= 1.00000000
[199, 13] n=000000dc r= 1.10000000
[ 7, 15] n=000000f0 r= 1.20000000
[ 71, 16] n=00000104 r= 1.30000000
[135, 17] n=00000118 r= 1.40000000
[ 15, 6] n=00000060 r= 1.50000000
[ 7, 20] n=00000140 r= 1.60000000
[ 71, 21] n=00000154 r= 1.70000000
[135, 22] n=00000168 r= 1.80000000
[199, 23] n=0000017c r= 1.90000000
[ 4, 0] n=00000002 r= 2.00000000