1

Тема: Дуже "просте" перетворення з цікавим алгоритмом

Друзі. Зламав свій мозочок над простим перетворенням 8 бітного числа.
Є одне число що потрібно перетворити в інше, за дуже простим алгоритмом який має вісім варіантів.
а - вхідний байт; б - перетворений.
1) б(біт 0) = а(біт 0)
2) б(біт 0) = а(біт 1); б(біт 1) = а(біт 0);
3) б(біт 0) = а(біт 2); б(біт 1) = а(біт 1); б(біт 2) = а(біт 0);
4) б(біт 0) = а(біт 3); б(біт 1) = а(біт 2); б(біт 2) = а(біт 1); б(біт 3) = а(біт 0);
https://replace.org.ua/extensions/om_images/img/61082c651459c/2l1natp821.png
І так далі. Якщо уважно прочитати, то можно побачити що дані з байту "а" записуються в ьайт "б", де що перевернутими ззаду наперд. Але перевертається не весь байт а окрема його частина в залежності від варіанту... Ось що я натулив поки ламав головешку

Прихований текст
short a = 0x01, b;
short variants;

if(variants == 1)
{
    b |= a & 0x01;
}

if(variants == 2)
{
    b |= (a & 0x01) << 1; // Здвиг біта №0 на 1 вперед
    b |= (a & 0x02) >> 1; // Здвиг біта №1 на 1 назад
    // в байті b буде число 0x02
}

if(variants == 3)
{
    b |= (a & 0x01) << 2; // Здвиг біта №0 на 2 вперед
    b |= a & 0x02;
    b |= (a & 0x04) >> 2; // Здвиг біта №2 на 2 назад
    // в байті b буде число 0x04
}

if(variants == 4)
{
    b |= (a & 0x01) << 3; // Здвиг біта №0 на 2 вперед
    b |= (a & 0x02) << 1; // Здвиг біта №1 на 1 вперед
    b |= (a & 0x04) >> 1; // Здвиг біта №2 на 1 назад
    b |= (a & 0x08) >> 2; // Здвиг біта №3 на 2 назад
    // в байті b буде число 0x04
}
// і так далі...

Так, я роблю це в ручну, і здається мені що це не оптимізовано і взагалі не правильно. Шановні Гуру, може щось підкажете?

2 Востаннє редагувалося koala (03.08.2021 06:12:21)

Re: Дуже "просте" перетворення з цікавим алгоритмом

Тип даних, що вміщає байт - це char, але якщо вам треба його повністю використовувати без проблем - то unsigned char, інакше зсув старшого біта може бути дещо дивним. Гадаю, ви тому short і обрали - щоб старший біт був у іншому байті.

using Byte = unsigned char;

А тепер банальний цикл

Byte a = 0x0E, b = 0x0; //зануляти b треба!
int size = 4;

for(int i = 0; i < size; ++i)
    b |= ( (a >> i) & 1 ) << (size - i - 1);//

Зсуваємо не 1, а a - тоді легше зрозуміти, куди той біт зсувати назад.

Перепрошую за можливі помилки, пишу з телефону

Подякували: Si4karuk1

3

Re: Дуже "просте" перетворення з цікавим алгоритмом

Уточніть всесвіт, у якому це треба зробити.

Якщо це просто цікаво бітами помахати, то читати bit twiddling hacks

Якщо є конкретна задача для конкретного процесорного ядра, то, для сучасних, дуже ймовірно що є зручні команди, які у вигляді тих чи інших макросів чи вбудованих (built-in) функцій підтримує будь-який  компілятор для цієї архітектури.

Якщо це має працювати на будь-чому, для чого є C, то перше, виділити у окрему функцію, тоді за потреби під #ifdef-и1 запхати спеціалізовані під компілятор/архітектуру швидкі варіанти.

____________________________
1 Код, напханий #ifdef-ами, це не "переносимий код", а код, який багато разів переносили © не знаю чий

Подякували: P.Y.1

4

Re: Дуже "просте" перетворення з цікавим алгоритмом

    a = (a & 0x55) << 1 | (a & 0xAA) >> 1;
    a = (a & 0x33) << 2 | (a & 0xCC) >> 2;
    a = (a & 0x0F) << 4 | (a & 0xF0) >> 4;

    b = a >> 8 - variant;