使用一个字节表示3个整数?

use*_*424 3 binary-data character-encoding primitive-types

我有三个整数{ a,b,c下面的值之间}该范围(比方说):

a - {1到120,跳跃1}

b - {-100到100,跳跃为5}

c - {1到10,跳跃1}

由于空间的考虑,我想表示使用1字节ONLY,意义,一个整数(在-127..128的范围内)这三个值将代表的{结果a,b,c},并被存储在二进制格式化为磁盘.

后来,当我读到的二进制数据,我会知道如何"解析"这1个字节得到的值{ a,b,c}.

知道如何实现吗?(注意:如果需要,为了支持这种设计,我可以在范围上"妥协";例如,a可以在5的跳跃中b也可以在10等的跳跃中)

Mik*_*ley 6

从数字的角度来看,我们有:

a = 120个值,b = 41个值,c = 10个值

这使得总共有49,200个唯一值.一个字节只能表示256个值,因此您需要使用至少16位(两个字节)来表示您的范围.

一种方法是通过位移.

例如,您可以在32位值中存储四个8位值,并像这样提取它们:

#include <iostream>
using namespace std;


int pack32(char *v)
{
    return (v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3];
}

void unpack32(int a, char *v)
{
    v[0] = a >> 24;
    v[1] = a >> 16;
    v[2] = a >> 8;
    v[3] = a;
}

int main()
{
    char v[4] = {32, 64, 16, 8};

    cout << "Original values: ";
    for (int i = 0; i < 4 ; i++)
        cout << (int)v[i] << " ";
    cout << endl;

    int q = pack32(v);
    cout << "Packed: " << q << endl;

    unpack32(q, v);
    cout << "Unpacked: ";
    for (int i = 0; i < 4; i++)
        cout << (int)v[i] << " ";

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

与您的需求相关的代码:

unsigned short pack32(unsigned a, char b, unsigned c)
{
    // Layout:
    // Bits 0 - 5 are reserved for a
    // Bits 6 - 12 are reserved for b
    // Bits 13 - 15 are reserved for c

    // Assumptions:
    // a is [2, 120] in steps of 2
    // b is [-100, 100] in steps of 5
    // c is [1, 10] in steps of 1

    // Shift a from [2, 120] to [0, 59]
    unsigned a2 = (a - 2) >> 1;
    // Shift b from [-100, 100] to [0, 40]
    unsigned b2 = b / 5 + 20;
    // Shift c from [1, 10] to [0, 9]
    unsigned c2 = c - 1;

    return a2 + (b2 << 5) + (c2 << 12);
}
Run Code Online (Sandbox Code Playgroud)