C++ cli 用于压缩和解压缩整数数组的函数 我最近被要求完成一个C++角色的任务,但是由于应用程序被决定不再进行进一步的开发,我想我会在这里发布一些我已经忘记的反馈/建议/改进/提醒概念。

C++ cli 用于压缩和解压缩整数数组的函数 我最近被要求完成一个C++角色的任务,但是由于应用程序被决定不再进行进一步的开发,我想我会在这里发布一些我已经忘记的反馈/建议/改进/提醒概念。,c++-cli,compression,C++ Cli,Compression,任务是: 以下数据是整数值的时间序列 int timeseries[32] = {67497, 67376, 67173, 67235, 67057, 67031, 66951, 66974, 67042, 67025, 66897, 67077, 67082, 67033, 67019, 67149, 67044, 67012, 67220, 67239, 66893, 66984, 66866, 66693, 66770, 66722, 66620, 66579, 66596, 66713,

任务是:

以下数据是整数值的时间序列

int timeseries[32] = {67497, 67376, 67173, 67235, 67057, 67031, 66951,
66974, 67042, 67025, 66897, 67077, 67082, 67033, 67019, 67149, 67044,
67012, 67220, 67239, 66893, 66984, 66866, 66693, 66770, 66722, 66620,
66579, 66596, 66713, 66852, 66715};
例如,该系列可能是股票每天的收盘价 超过32天

如上所述,数据将占用
32 x sizeof(int)字节=128字节
假设4字节整数

使用增量编码,编写一个要压缩的函数,以及一个要压缩的函数 像上面那样解压缩数据

好的,在这之前我从来没有研究过压缩,所以我的解决方案还远远不够完美。我处理这个问题的方式是将整数数组压缩为字节数组。当将整数表示为字节时,我保留了最长的计算时间 有效字节(msb),并将所有内容保持到这一点,同时丢弃其余内容。然后将其添加到字节数组中。对于负值,我将msb增加1,以便 在解码时通过保持前导来区分正字节和负字节 1位值

解码时,我解析这个锯齿形字节数组,并简单地反转 压缩时执行的先前操作。如前所述,在执行此任务之前,我从未研究过压缩,因此我确实提出了自己的方法来压缩数据。我最近在看C++/Cli,以前没有真正使用过它,所以决定用这种语言编写它,没有特别的原因。下面是课程,最下面是单元测试。如有任何建议/改进/增强,将不胜感激

谢谢

array<array<Byte>^>^ CDeltaEncoding::CompressArray(array<int>^ data)
{
    int temp = 0;
    int original;
    int size = 0;

    array<int>^ tempData = gcnew array<int>(data->Length);
    data->CopyTo(tempData, 0);

    array<array<Byte>^>^ byteArray = gcnew array<array<Byte>^>(tempData->Length);

    for (int i = 0; i < tempData->Length; ++i)
    {
            original = tempData[i];
            tempData[i] -= temp;
            temp = original;

            int msb = GetMostSignificantByte(tempData[i]);

            byteArray[i] = gcnew array<Byte>(msb);
            System::Buffer::BlockCopy(BitConverter::GetBytes(tempData[i]), 0, byteArray[i], 0, msb );

            size += byteArray[i]->Length;
    }

    return byteArray;
}

array<int>^ CDeltaEncoding::DecompressArray(array<array<Byte>^>^ buffer)
{
    System::Collections::Generic::List<int>^ decodedArray = gcnew System::Collections::Generic::List<int>();

    int temp = 0;

    for (int i = 0; i < buffer->Length; ++i) 
    {
            int retrievedVal = GetValueAsInteger(buffer[i]);
            decodedArray->Add(retrievedVal);

            decodedArray[i] += temp;
            temp = decodedArray[i];
    }

    return decodedArray->ToArray();
}

int CDeltaEncoding::GetMostSignificantByte(int value)
{
    array<Byte>^ tempBuf = BitConverter::GetBytes(Math::Abs(value));

    int msb = tempBuf->Length;

    for (int i = tempBuf->Length -1; i >= 0; --i)
    {
            if (tempBuf[i] != 0)
            {
                    msb = i + 1;
                    break;
            }
    }

    if (!IsPositiveInteger(value))
    {
            //We need an extra byte to differentiate the negative integers
            msb++;
    }

    return msb;
}

bool CDeltaEncoding::IsPositiveInteger(int value)
{
    return value / Math::Abs(value) == 1;
}

int CDeltaEncoding::GetValueAsInteger(array<Byte>^ buffer)
{
    array<Byte>^ tempBuf;

    if(buffer->Length % 2 == 0)
    {
            //With even integers there is no need to allocate a new byte array
            tempBuf = buffer;
    }
    else
    {
            tempBuf = gcnew array<Byte>(4);
            System::Buffer::BlockCopy(buffer, 0, tempBuf, 0, buffer->Length );

            unsigned int val = buffer[buffer->Length-1] &= 0xFF;

            if ( val == 0xFF )
            {
                    //We have negative integer compressed into 3 bytes
                    //Copy over the this last byte as well so we keep the negative pattern
                    System::Buffer::BlockCopy(buffer, buffer->Length-1, tempBuf, buffer->Length, 1 );
            }
    }

    switch(tempBuf->Length)
    {
    case sizeof(short):
            return BitConverter::ToInt16(tempBuf,0);
    case sizeof(int):
    default:
            return BitConverter::ToInt32(tempBuf,0);
    }
}
array^CDeltaEncoding::CompressArray(数组^data)
{
内部温度=0;
int原件;
int size=0;
数组^tempData=gcnew数组(数据->长度);
数据->复制到(tempData,0);
数组^byteArray=gcnew数组(tempData->Length);
对于(int i=0;iLength;++i)
{
原始=临时数据[i];
tempData[i]=temp;
温度=原件;
int msb=GetMostSignificantByte(tempData[i]);
byteArray[i]=gcnew数组(msb);
System::Buffer::BlockCopy(位转换器::GetBytes(tempData[i]),0,byteArray[i],0,msb);
大小+=字节数组[i]->长度;
}
乘火车返回;
}
数组^CDELTAENCODE::解压缩数组(数组^buffer)
{
System::Collections::Generic::List^decodedArray=gcnew System::Collections::Generic::List();
内部温度=0;
对于(int i=0;iLength;++i)
{
int retrievedVal=GetValueAsInteger(缓冲区[i]);
decodedArray->Add(retrievedVal);
解码Darray[i]+=温度;
温度=达雷[i];
}
返回decodedArray->ToArray();
}
int CDELTAENCODE::GetMostSignificantByte(int值)
{
数组^tempBuf=BitConverter::GetBytes(数学::Abs(值));
int msb=tempBuf->Length;
对于(inti=tempBuf->Length-1;i>=0;--i)
{
如果(tempBuf[i]!=0)
{
msb=i+1;
打破
}
}
如果(!IsPositiveInteger(值))
{
//我们需要一个额外的字节来区分负整数
msb++;
}
返回msb;
}
布尔CDELTAENCODE::IsPositiveInteger(int值)
{
返回值/数学::Abs(值)==1;
}
int CDELTAENCODE::GetValueAsInteger(数组^buffer)
{
数组^tempBuf;
如果(缓冲区->长度%2==0)
{
//对于偶数整数,不需要分配新的字节数组
tempBuf=缓冲区;
}
其他的
{
tempBuf=gc新阵列(4);
System::Buffer::BlockCopy(Buffer,0,tempBuf,0,Buffer->Length);
无符号int val=buffer[buffer->Length-1]&=0xFF;
如果(val==0xFF)
{
//我们将负整数压缩为3个字节
//复制最后一个字节,所以我们保持负模式
System::Buffer::BlockCopy(Buffer,Buffer->Length-1,tempBuf,Buffer->Length,1);
}
}
开关(tempBuf->Length)
{
箱子尺寸(短):
返回位转换器::ToInt16(tempBuf,0);
案例大小(整数):
违约:
返回位转换器::ToInt32(tempBuf,0);
}
}
然后在一个测试课上,我有:

void CTestDeltaEncoding::TestCompression()
{
    array<array<Byte>^>^ byteArray = CDeltaEncoding::CompressArray(m_testdata);

    array<int>^ decompressedArray = CDeltaEncoding::DecompressArray(byteArray);

    int totalBytes = 0;
    for (int i = 0; i<byteArray->Length; i++)
    {
            totalBytes += byteArray[i]->Length;
    }

    Assert::IsTrue(m_testdata->Length * sizeof(m_testdata) > totalBytes, "Expected the total bytes to be less than the original array!!");

    //Expected totalBytes = 53
}
void CTestDeltaEncoding::TestCompression()
{
数组^byteArray=CDELTAENCODE::CompressArray(m_testdata);
数组^decompressedArray=cdeltaencode::DecompressArray(byteArray);
int totalBytes=0;
对于(int i=0;i长度;i++)
{
totalBytes+=字节数组[i]->长度;
}
Assert::IsTrue(m_testdata->Length*sizeof(m_testdata)>totalBytes,“期望总字节数小于原始数组!!”;
//预期总字节数=53
}

这对我来说很像家庭作业。关键的短语是:“使用增量编码。”

增量编码是指对每个数字和下一个数字之间的增量(差)进行编码:

67497、67376、67173、67235、67057、67031、66951、66974、67042、67025、66897、67077、67082、67033、67019、67149、67044、67012、67220、67239、66893、66984、66866、66693、66770、66722、66620、66579、66596、66713、66852、66715

将变成:

[基数:67497]:-121,-203,+62

等等。假设为8位字节,原始数字每个需要3个字节(如果编译器的数量为3字节整数类型,则通常每个编译器需要4个字节)。从外观上看,差异很容易在每个字节中匹配2个字节,如果可以忽略最低有效位中的一个(或可能两个),则可以在每个字节中匹配它们

增量编码最常用于声音编码之类的事情,在这种情况下,您有时可以使用0来“伪造”准确度