Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何有效地将8个17位整数转换为17个8位整数_C++_Integer - Fatal编程技术网

C++ 如何有效地将8个17位整数转换为17个8位整数

C++ 如何有效地将8个17位整数转换为17个8位整数,c++,integer,C++,Integer,好的,我有以下问题:我有一组8(无符号)的数字,它们都是17位的(也就是说,没有一个大于131071)。由于17位数字是令人讨厌的工作(将它们保持在32位整数是浪费空间),我想将它们转换为17个8位数字,如下所示: 如果我有8个17位整数: [25409, 23885, 24721, 23159, 25409, 23885, 24721, 23159] 我会把他们变成基地2的代表 ["00110001101000001", "00101110101001101", "0011000001001

好的,我有以下问题:我有一组8(无符号)的数字,它们都是17位的(也就是说,没有一个大于131071)。由于17位数字是令人讨厌的工作(将它们保持在32位整数是浪费空间),我想将它们转换为17个8位数字,如下所示:

如果我有8个17位整数:

[25409, 23885, 24721, 23159, 25409, 23885, 24721, 23159]
我会把他们变成基地2的代表

["00110001101000001", "00101110101001101", "00110000010010001", "00101101001110111", "00110001101000001", "00101110101001101", "00110000010010001", "00101101001110111"]
然后将其连接成一根大绳:

"0011000110100000100101110101001101001100000100100010010110100111011100110001101000001001011101010011010011000001001000100101101001110111"
然后将其拆分为17个字符串,每个字符串包含8个字符:

["00110001", "10100000", "10010111", "01010011", "01001100", "00010010", "00100101", "10100111", "01110011", "00011010", "00001001", "01110101", "00110100", "11000001", "00100010", "01011010", "01110111"]
最后,将二进制表示转换回整数

[49, 160, 151, 83, 76, 18, 37, 167, 115, 26, 9, 117, 52, 193, 34, 90, 119]

这个方法有效,但效率不高,我在寻找比C++更有效的东西,因为我正在使用的语言。我想不出任何更有效的方法,17位数字并不容易处理(16位数字会更好)


提前感谢,xfbs按原样存储每个数字的最低16位(即两个字节)。这将保留每个数字的最高有效位。由于有八个这样的数字,只需将八位合并成一个额外的字节

这将需要与您的方法完全相同的内存量,但将涉及更少的位旋转


另外,无论采用何种存储方法,您都应该使用位操作运算符(
&
|
等)来完成这项工作;不应涉及任何基于字符串的中间表示。

请查看
std::bitset
。也许你可以把它们塞进那个里?

这是用C写的,所以你可以用向量来代替

#define srcLength 8
#define destLength 17
int src[srcLength] = { 25409, 23885, 24721, 23159, 25409, 23885, 24721, 23159 };
unsigned char dest[destLength] = { 0 };

int srcElement = 0;
int bits = 0;
int i = 0;
int j = 0;

do {
    while( bits >= srcLength ) {
        dest[i++] = srcElement >> (bits - srcLength);
        srcElement = srcElement & ((1 << bits) - 1);
        bits -= srcLength;
    }

    if( j < srcLength ) {
        srcElement <<= destLength;
        bits += destLength;
        srcElement |= src[j++];
    }
} while (bits > 0);
#定义src长度8
#定义长度17
int src[srcLength]={25409、23885、24721、23159、25409、23885、24721、23159};
无符号字符dest[destLength]={0};
int src元素=0;
整数位=0;
int i=0;
int j=0;
做{
while(位>=src长度){
dest[i++]=src元素>>(位-src长度);

srcElement=srcElement&((1有效?那么不要使用字符串转换、位字段等。请设法自己进行移位来实现这一点。(请注意,数组必须是
无符号的
,以便在移位时不会遇到问题)

对于最后一个,我们按照ajx所说的做。我们取每个数字的最高有效位(将其右移16位,留下第17位),并通过将每个最高有效位从0向左移动7位来填充输出的位:

B[16] = (A[0] >> 16)  | ((A[1] >> 16) << 1) | ((A[2] >> 16) << 2) | ((A[3] >> 16) << 3) | ... | ((A[7] >> 16) << 7);

B[16]=(A[0]>>16)|((A[1]>>16)>16)虽然你说它们是17位的数字,但它们必须存储在32位整数的数组中,其中只使用低有效的17位。你可以直接从前两个字节中提取(
dst[0]=src[0]>>9
是第一个,
dst[1]=(src[0]>1)&0xff
第二位);然后将第一位“推”为第二位的第18位,以便

  dst[2] = (src[0] & 1) << 7 | src[1] >> 10;
  dst[3] = (src[1] >> 2) & 0xff;
可能更好地分析循环,可以进行优化,这样我们就不需要以特殊方式处理边界上的情况。BITS宏创建一个N位掩码,将其设置为1(最低有效位)。类似于(如果有更好的方法,请检查)


#定义位(I)(~(~0)我可能会这样做。我不想在处理时处理奇怪的类型。不过,可能由于遗留问题,我需要将它们存储在一些时髦的格式中。硬编码的值可能应该基于17值,只是不需要麻烦

struct int_block {
    static const uint32 w = 17;
    static const uint32 m = 131071;
    int_block() : data(151, 0) {} // w * 8 + (sizeof(uint32) - w)
    uint32 get(size_t i) const {
        uint32 retval = *reinterpret_cast<const uint32 *>( &data[i*w] );
        retval &= m;
        return retval;
    }
    void set(size_t i, uint32 val) {
        uint32 prev = *reinterpret_cast<const uint32 *>( &data[i*w] );
        prev &= ~m;
        val |= prev;
        *reinterpret_cast<uint32 *>( &data[i*w] ) = val;
    }
    std::vector<char> data;
};

TEST(int_block_test) {

    int_block ib;
    for (uint32 i = 0; i < 8; i++)
        ib.set(i, i+25);

    for (uint32 i = 0; i < 8; i++)
        CHECK_EQUAL(i+25, ib.get(i));
}
struct int_块{
静态常数uint32 w=17;
静态常数uint32 m=131071;
int_block():数据(151,0){}//w*8+(sizeof(uint32)-w)
uint32 get(尺寸)常数{
uint32 retval=*重新解释铸件和数据[i*w];
retval&=m;
返回返回;
}
无效集(尺寸i,uint32 val){
uint32 prev=*重新解释铸件和数据[i*w];
prev&=~m;
val |=上一个;
*重新解释(数据[i*w])=val;
}
std::矢量数据;
};
测试(内部块测试){
int_block ib;
对于(uint32 i=0;i<8;i++)
ib.set(i,i+25);
对于(uint32 i=0;i<8;i++)
检查_等于(i+25,ib.get(i));
}
你可以通过给它错误的值来打破它,但我将把它留给读者作为练习。:)


老实说,我认为如果将它们表示为32位整数并只编写转换函数,您会更高兴。但我怀疑您无法控制这一点。

您正在开发的平台是什么,您担心将它们存储在32位整数中会浪费空间?@Praetorian:可能是任何可用内存较少的平台“数据的大小不可能是原来的两倍。@Steve Jessop,这个数字不可能是原来的两倍,只是空间增加了88%:-)但是说真的,如果程序的其他部分希望这些数字是17位整数,而不是一个紧挨着的字节数组,那么OP必须将它们重新转换为17位表示。是否他用所有的格式转换代码来节省内存。你担心的是什么标准?效率?速度?内存?磁盘序列化?我也很好奇平台问题,这似乎是你在过度思考它是否没有什么特别之处。事实上,我不太担心浪费空间,另一个原因是我可以导出8bit inte很容易:它们正好有合适的大小,可以将它们转换为字符,然后我可以将整个内容导出为字符串。我也可以将它们填充到向量中,但这有什么用呢?位集是否有以不同形式导出数据的功能(8bit int)?这个答案的目的是完全重新设计您的程序,使其始终使用
std::bitset
,而不是进行重新打包。@xfbs,您没有向我们提供详细信息,因此我无法回答您的问题。@Unkulu好的,w
   dst[2*i] = src[i] >> (9+i) | (src[i-1] & BITS(i)) << (8-i);
   dst[2*i + 1] = (src[i] >> (i+1)) & 0xff;
  dst[0] = src[0] >> 9;
  dst[1] = (src[0] >> 1) & 0xff;

  for(i = 1; i < 8; i++)
  {
    dst[2*i] = src[i] >> (9+i) | (src[i-1] & BITS(i)) << (8-i);
    dst[2*i + 1] = (src[i] >> (i+1)) & 0xff;
  }
  dst[16] = src[7] & 0xff;
#define BITS(I) (~((~0)<<(I)))
struct int_block {
    static const uint32 w = 17;
    static const uint32 m = 131071;
    int_block() : data(151, 0) {} // w * 8 + (sizeof(uint32) - w)
    uint32 get(size_t i) const {
        uint32 retval = *reinterpret_cast<const uint32 *>( &data[i*w] );
        retval &= m;
        return retval;
    }
    void set(size_t i, uint32 val) {
        uint32 prev = *reinterpret_cast<const uint32 *>( &data[i*w] );
        prev &= ~m;
        val |= prev;
        *reinterpret_cast<uint32 *>( &data[i*w] ) = val;
    }
    std::vector<char> data;
};

TEST(int_block_test) {

    int_block ib;
    for (uint32 i = 0; i < 8; i++)
        ib.set(i, i+25);

    for (uint32 i = 0; i < 8; i++)
        CHECK_EQUAL(i+25, ib.get(i));
}