Хранение int16_t в uint64_t

Итак, у меня есть 4 uint16_t, и я пытаюсь сохранить их в одном uint64_t. Я думаю, что у меня это работает.

uint64_t encode(int16_t A, int16_t B, int16_t C, int16_t D){
    return (uint64_t)((uint16_t) A) << 48
         | (uint64_t)((uint16_t) B) << 32
         | (uint64_t)((uint16_t) C) << 16
         | (uint64_t)((uint16_t) D) <<  0;
}

int main(){

    int16_t A1 = -32000;
    int16_t B1 = -31000;
    int16_t C1 = 16004;
    int16_t D1 = 16007;

    uint16_t A2 = 32000;
    uint16_t B2 = 15000;
    uint16_t C2 = -4;
    uint16_t D2 = -7;

    uint64_t E = encode(A1, B1, C1, D1)
               + encode(A2, B2, C2, D2);

    printf("%d\n", (int16_t)((E >> 48)));
    printf("%d\n", (int16_t)((E >> 32)));
    printf("%d\n", (int16_t)((E >> 16)));
    printf("%d\n", (int16_t)((E >>  0)));
}

Я был в состоянии закодировать 4 int16_t, а затем вернуть их, используя этот метод. Теперь я хотел бы сложить вместе две закодированные формы, декодировать их и вернуться к исходной операции. Я, кажется, получаю кучу off на 1 ошибки.

Мой вывод здесь 0, -15999, 16001, 16000. Два выхода правильные (0 и 16000) и два выключены по одному.

Я отмечу, что я попытался сначала преобразовать int16_t в uint16_t (добавить 32768), но безуспешно.

1 ответ

Решение

Вы получаете переход с одного номера на другой. Точно так же, как если бы вы закодировали десятичные числа 1 а также 9 как 19, 2 а также 3 как 23 а затем сложили их вместе: 19 + 23 = 42, но 1 + 2 = 3, Таким образом, верхняя цифра "от одного".

Даже если вы хотите избежать полной распаковки, вы можете сделать что-то вроде:

result = 
  ((a&0xffff0000ffff0000 + b&0xffff0000ffff0000) & 0xffff0000ffff0000) |
   (a&0x0000ffff0000ffff + b&0x0000ffff0000ffff) & 0x0000ffff0000ffff))

... который действует в два этапа, чтобы избежать неуместного переноса.

Другие вопросы по тегам