Могу ли я использовать типы данных, такие как bool, для сжатия данных при улучшении читабельности?

Мой официальный вопрос будет звучать так: «Есть ли чистый способ использовать типы данных для« кодирования и сжатия »данных, а не использовать грязную битовую маскировку». Надежды будут состоять в том, чтобы сэкономить место в случае сжатия, и я хотел бы использовать собственные типы данных, структуры и массивы, чтобы улучшить читаемость по сравнению с битовой маскировкой. Я хорошо разбираюсь в маске, но я изучаю C ++ и ООП. Мы можем хранить столько информации в 32-битном регистре, используя отдельные биты, и я чувствую, что пытаюсь вернуться в среду низкого уровня, читая код C ++.

Я пытаюсь сэкономить место, потому что работаю с огромными ресурсами. Я все еще узнаю больше о том, как C ++ относится к bool тип данных. Я понимаю, что память хранится в байтах, а не в отдельных битах. Я считаю, что bool обычно использует один байт и как-то маскируется. В моей голове я мог использовать 8 bool значения в одном байте.

Если я malloc в C ++ массив 2 bool элементы. Выделяет ли он два байта или только один?

Пример: мы будем использовать ДНК в качестве примера, поскольку она может быть закодирована в два бита для представления A, C, G и T. Если я создаю структуру с массивом из двух bool называется DNA_Base, тогда я делаю массив из 20 из них.

struct DNA_Base{  bool Bit_1;  bool Bit_2; };
DNA_Base DNA_Sequence[7] = {false};
cout << sizeof(DNA_Base)<<sizeof(DNA_Sequence)<<endl;
//Yields a 2 and a 14.
//I would like this to say 1 and 2.

В моем примере я бы также показал случай, когда последовательность ДНК может иметь длину 20 оснований, что для кодирования потребовало бы 40 битов. GATTACA может занимать максимум 2 байта? Я полагаю, что альтернативным вопросом было бы «Как заставить C ++ делать битовую маскировку для меня более читабельным способом» или я должен просто создать свой собственный тип данных и классы и реализовать битовую маскировку, используя классы и перегрузку операторов.

1

Решение

Не совсем то, что вы хотите, но вы можете использовать битовое:

struct DNA_Base
{
unsigned char Bit_1 : 1;
unsigned char Bit_2 : 1;
};
DNA_Base DNA_Sequence[7];

Так sizeof(DNA_Base) == 1 а также sizeof(DNA_Sequence) == 7

Таким образом, вы должны упаковать DNA_Base чтобы не потерять место с набивка, что-то вроде:

struct DNA_Base_4
{
unsigned char base1 : 2; // may have value 0 1 2 or 3
unsigned char base2 : 2;
unsigned char base3 : 2;
unsigned char base4 : 2;
};

Так sizeof(DNA_Base_4) == 1

std::bitset Это другая альтернатива, но вы должны сделать работу по переводу самостоятельно.

2

Другие решения

Массивом bools будет N-элементов x sizeof (bool).

Если ваша цель — сэкономить место в регистрах, не беспокойтесь, потому что на самом деле эффективнее использовать размер слова для рассматриваемого процессора, чем использовать один байт, и компилятор все равно предпочтет использовать слово, поэтому в структуре / классе bool обычно расширяется до 32-битного или 64-битного собственного слова.

Теперь, если вы хотите сэкономить место на диске или в оперативной памяти, из-за необходимости хранить много вариантов bools, продолжайте, но это не сэкономит места во всех случаях, если вы не упакуете структуру, и на некоторых архитектурах Упаковка также может повлиять на производительность, так как ЦП должен будет выполнять не выровненный или побайтовый доступ.

Битовая маска (или битовое поле), с другой стороны, является производительной и эффективной и настолько плотной, насколько это возможно, и использует одну побитовую операцию. Я хотел бы взглянуть на один из абстрактных типов данных, которые предоставляют битовые поля.

Стандартная библиотека имеет битсет http://www.cplusplus.com/reference/bitset/bitset/ который может быть так долго, как вы хотите.

У Boost тоже есть кое-что, я уверен.

0

Если вы не находитесь на 4-битной машине, конечный результат будет использовать битовую арифметику. Независимо от того, выполняете ли вы это явно, если компилятор делает это через битовые поля или использует битовый контейнер, будет битовая манипуляция.

Я предлагаю следующее:

  • Используйте существующие библиотеки сжатия.
  • Используйте метод, который наиболее читаем или понятен людям
    чем ты.
  • Используйте метод, который является наиболее продуктивным (говорить о разработке
    время).
  • Используйте метод, которым вы будете вводить наименьшее количество дефектов.

Изменить 1:
Запишите каждый метод как отдельную функцию.
Скажите компилятору, чтобы он генерировал язык ассемблера для каждой функции.
Сравните язык ассемблера каждой функции друг с другом.

Я считаю, что они будут очень похожи, достаточно того, что тратить время на их обсуждение не стоит.

0

Вы не можете работать с битами напрямую, но вы можете рассматривать наименьшую единицу, доступную вам, как хранилище нескольких данных, и определять

enum class DNAx4 : uint8_t {
AAAA = 0x00, AAAC = 0x01, AAAG = 0x02, AAAT = 0x03,
// .... And the rest of them
AAAA = 0xFC, AAAC = 0xFD, AAAG = 0xFE, AAAT = 0xFF
}

Я бы на самом деле пошел дальше и создал бы структуру DNAx16 или DNAx32, чтобы эффективно использовать собственный размер слова на вашей машине.

Затем вы можете определить функции для типа данных, которые должны будут использовать базовое представление битов, но, по крайней мере, это позволяет вам инкапсулировать это и строить операции более высокого уровня из этих примитивов.

0
По вопросам рекламы [email protected]