Compression unit test data "easy case" In another post I created a piece of data, which make compressor annoyed.

Create &#39;worst case test&#39; data for compression test

Now I am trying to make it happy.  I generate another data set, with a lot of duplicated binarys.  Of couse a data set composed of only one value is the best, but that is too easy.

This time I use a random number generator.  Inside a loop, each time either add a new byte or duplicate some bytes until reach a predefined length.

#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;random&gt;
#include &lt;vector&gt;

typedef std::vector&lt;unsigned char&gt; Data;

int main(int argc, char* argv[])
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution&lt;double&gt; rand(0.0, std::nextafter(1.0, DBL_MAX));

    const unsigned int length = 0x10000; // file minimal size

    Data data;
    data.reserve(length * 2);
    while (data.size() &lt; length)
    {
        if (data.size() &lt;= 1 || rand(mt) &lt; 0.5)
        {
            // add a new byte
            data.push_back((unsigned char)(rand(mt) * 256)); 
        }
        else
        {
            // duplicate some bytes
            unsigned int count = (unsigned int)(rand(mt) * (data.size() / 2) + 1);
            data.insert(data.end(), data.end() - count, data.end());
        }
    }

    const char* filename = "c:\\_Test\\easy.dat";
    std::ofstream ofs(filename, std::ios::binary);
    if (ofs.bad() || !ofs.is_open())
    {
        std::cerr &lt;&lt; "fail to open file\n";
        return -1;
    }
    ofs.write((char*)data.data(), data.size());

    std::cout &lt;&lt; "job done\n";
    return 0;
}


The 7-zip is extremely happy with it.  With 7z format, 90kb data compressed to 900 bytes, and with zip format, it compressed to less than 2kb. 

Again any suggestions and help are appreciated.
A few thoughts:

1. Don't use C-style casts

Here

 data.push_back((unsigned char)(rand(mt) * 256)); 
             // ^^^^^^^^^^^^^^^


and here 

 unsigned int count = (unsigned int)(rand(mt) * (data.size() / 2) + 1);
                   // ^^^^^^^^^^^^^^


you use (unchecked) C-style cast operations. I C++ all casts should be either checked, or explicitly a reinterpret_cast (which is merely the same, but clearly shows intention).

In your cases a static_cast&lt;unsigned char&gt; and a static_cast&lt;unsigned int&gt; seems to be more appropriate for me.

2. If you're dealing with plain integer numbers prefer using std::uniform_int_distribution

You are using std::uniform_real_distribution&lt;double&gt;

std::uniform_real_distribution&lt;double&gt; rand(0.0, std::nextafter(1.0, DBL_MAX));


to finally generate integer types (done through implicit conversion).

It would seem more appropriate to use 

 std::uniform_int_distribution&lt;unsigned int&gt; rand(0, std::nextafter(1, UINT_MAX) /* intentional ?? */ );


or even better simply

std::uniform_int_distribution&lt;unsigned int&gt; rand();


and 

data.push_back(static_cast&lt;unsigned char&gt;
    (rand(mt) % std::numeric_limits&lt;unsigned char&gt;::max()); 
// ...
unsigned int count = rand(mt) * (data.size() / 2) + 1;


Floating point conversions and calculations may cause unnecessary overhead in the emitted assembly instructions.

3. Prefer std::numeric_limits over the C-style macro definitions

In C++ you should prefer using std::numeric_limits&lt;double&gt;::max() over the DBL_MAX C-style macro.

At least with GCC I always get compiler errors using these constants (even though &lt;cstdint&gt; was included).

4. Modularize your code to be resuable

As you tagged this with unit-testing I would consider to create a little helper library API that can be used with the unit tests, without calling a separate program.

Instead of the int main(int argc, char* argv[]) entry point, refactor your code (including the stuff from Create 'worst case test' data for compression test) to a helper function API, that can be used easily with the various unit tests:

 namespace Test7ZipData {
     int create_worst_compressible_data(const char* filename);
     int create_easily_compressible_data(const char* filename);
     // int create_average_compressible_data(const char* filename); ????
 }


Compile these into a library, that will be linked with you unit tests.

5. Prefer using raw string literals instead of escaping special characters

Instead of 

const char* filename = "c:\\_Test\\easy.dat";


you can provide a raw string literal

const char* filename = R"(c:\_Test\easy.dat)";


That enhances readability of the literal text.