Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Реализация алгоритма перестановки 
:(
    Опции темы
Янус
Дата 14.2.2010, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 14.2.2010

Репутация: нет
Всего: нет



Господа, окажите пожалуйста помощь в реализации алгоритма перестановки на С++. Задача следующая: есть двоичное число размером в байт, биты этого числа нужно переставить по определенному правилу 0->5; 1->4; 2->8 и т.д.Или дайте ссылочку где об этом можно почитать.
PM MAIL   Вверх
Albor
Дата 14.2.2010, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 2
Всего: 9



В чём проблема? Проверить биты числа? Переставлять их не надо, поскольку есть только 2 значения 0 и 1, нужно только установить/сбросить соответствующий бит. 
Цитата(Янус @  14.2.2010,  18:34 Найти цитируемый пост)
правилу 0->5; 1->4; 2->8 и т.д

а и т.д. означает 3->6 (2->7, т.к. бита 8 в байте нет)? smile 

Это сообщение отредактировал(а) Albor - 14.2.2010, 18:51
PM MAIL ICQ   Вверх
Янус
Дата 14.2.2010, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 14.2.2010

Репутация: нет
Всего: нет



Нет биты надо именно переставить. Т.е до перестановки 00000001, после перестановки 00100000.
PM MAIL   Вверх
Albor
Дата 14.2.2010, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 2
Всего: 9



Цитата(Янус @  14.2.2010,  19:12 Найти цитируемый пост)
Нет биты надо именно переставить. Т.е до перестановки 00000001, после перестановки 00100000. 

Понимаешь, если бы цифер было больше, то можно говорить о перестановке, а так - просто нужно решить задачу. Если присмотреться к алгоритму, то можно увидеть, что 0 и 1 разряды младшего полубайта становятся соответствено 1-м и 0-м в старшем полубайте, то же самое и со старшими разрядами. Значит сначала можно просто поменять в младшем и старшем полубайте разряды местами : 0->1, 2->3, 4->5, 6->7. После сдвинуть младший полубайт влево, а старший вправо на 4 разряда. Объединив половинки получим целое.
Код

#include<iostream.h>

typedef unsigned char byte;

void main()
{
    cout.setf(ios::hex);
    byte b=0x55; // исходное число
    cout<<"before b = "<<(unsigned)b<<endl;
    byte c = (b & 0x55); // выделяем биты по маске 01010101
    byte d = (b & 0xAA);// выделяем биты по маске 10101010
    c<<=1;// сдвигаем влево на 1 разряд
    d>>=1;// сдвигаем вправо на 1 разряд
    b=c|d; // объединяем 
    c=(b & 0x0F);// запоминаем младший полубайт. маска 00001111
    c<<=4; // делаем младший старшим
    b>>=4;// а здесь наоборот
    b|=c; // объединяем результат
    cout<<"after b = "<<(unsigned)b<<endl;

}

PM MAIL ICQ   Вверх
bsa
Дата 14.2.2010, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Янус, в общем случае, тебе нужны побитовые операции: сдвиги, а так же операции "И" и "ИЛИ". Сдвигаешь число на N бит вправо и операцией "И" накладываешь маску 1. В результате получишь значение бита N. Затем результат сдвигаешь влево на M бит и операцией "ИЛИ" накладываешь на результат. Повторяешь для всех бит. Только не забудь обнулить результат перед началом действий.
PM   Вверх
Янус
Дата 14.2.2010, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 14.2.2010

Репутация: нет
Всего: нет



Господа, я дико извеняюсь, но чисел действительно больше, а именно 64.... Вот перестановочный вектор.
{0,8,16,24,32,40,48,56,1,9,17,25,33,41,49,57,2,10,18,26,34,42,50,58,3,11,19,27,35,43,51,59,4,12,20,28,36,44,52,60,5,
    13,21,29,37,45,53,61,6,14,22,30,38,46,54,62,7,15,23,31,39,47,55,63}; Т.е значения битов по номерам 0->0; 1->8;2->16 Значение бита с номером 0 остается на месте, а значение бита с номером 1 перебрасывется в бит с номером 8. Извените за некорректно поставленный вопрос. 
PM MAIL   Вверх
Янус
Дата 14.2.2010, 21:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 14.2.2010

Репутация: нет
Всего: нет



После долгих раздумий у меня получилось следующее...
Код

void perestanS64(int *a,char *b)//int *a это ссылка на перестановочный вектор, char *b это ссылка на bin число записанное в char массив.
{
    char c[65];
    for (int i=0;i<64;i++)
    {
        c[a[i]]=b[i];
        
    }
    for(int i=0;i<64;i++)
    {
        cout << c[i];
    }
}

Эта функция работает, но может, кто подправит ее (сделает более правильной ) или подскажет более оптимальное решение ?

PM MAIL   Вверх
Albor
Дата 14.2.2010, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 2
Всего: 9



Цитата(Янус @  14.2.2010,  21:18 Найти цитируемый пост)
{0,8,16,24,32,40,48,56,1,9,...

Если заполнить матрицу 8х8 последовательными значениями построчно, а потом прочитать её столбцами, ты получишь то же самое.  Перестановка битов здесь причём?
Код

#include<iostream.h>

typedef unsigned char byte;

void main()
{
    byte b[64];
    for(int i=0;i<8;i++)
    {
        for(int j=0;j<8;j++)
        {
            b[i*8+j]=j*8+i;
        }
    }
    for (i=0;i<64;i++) cout<<(unsigned)b[i]<<", ";
    cout<<endl;

}



Это сообщение отредактировал(а) Albor - 14.2.2010, 22:43
PM MAIL ICQ   Вверх
Albor
Дата 14.2.2010, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 2
Всего: 9



Цитата(Янус @  14.2.2010,  21:40 Найти цитируемый пост)
После долгих раздумий 

И я подумал, может я и не прав. 
Янус, можно пример входных и выходных данных?
PM MAIL ICQ   Вверх
Янус
Дата 14.2.2010, 23:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 14.2.2010

Репутация: нет
Всего: нет



На вход подается 64-битное двоичное число(записано в символьном массиве) , затем в нем меняются местами биты, с использованием вектора перестановки, по описанному выше правилу.
PM MAIL   Вверх
Albor
Дата 15.2.2010, 07:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 589
Регистрация: 28.2.2009

Репутация: 2
Всего: 9



Если правило не будет изменяться, то просто выводим исходный массив в нужной последовательности
Код

 for(int i=0;i<8;i++)
    {
        for(int j=0;j<8;j++)
        {
            cout<<b[j*8+i];
        }
    }


PM MAIL ICQ   Вверх
NewDima
Дата 15.2.2010, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: нет
Всего: 12



Код

inline int _getbit(char byte, int bit) {
    return (byte & (1 << bit)) >> bit;
}
// 1, 2, byteFrom, bitFrom, byteTo, bitTo
inline void _postoposa(char *vf, char *vt, int Bf, int bf, int Bt, int bt) {
    vt[Bt] = ((_getbit(vf[Bf], bf) << bt) | (vt[Bt] & (~(1 << bt))));
}
inline void _postopos(char *valueFrom, char *valueTo, int bitFrom, int bitTo) {
    _postoposa(valueFrom, valueTo, bitFrom/8, bitFrom%8, bitTo/8, bitTo%8);
}
template<typename T>
inline void movebit(T &valueFrom, T &valueTo, int bitIndex) {
    _postopos(reinterpret_cast<char*>(&valueFrom), reinterpret_cast<char*>(&valueTo), bitIndex, bitIndex%8*8 + bitIndex / 8);
}
    unsigned int v = 0x2;
    unsigned int k = 0;
    movebit(v, k, 1);

Так вроде работает, особо времени тестировать нет.  movebit перемещает бит с индексом bi из переменной vf в переменную vt по твоему правилу.
Прбеги по битам циклом
PM ICQ   Вверх
mes
Дата 15.2.2010, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(NewDima @  15.2.2010,  09:06 Найти цитируемый пост)
    return (byte & (1 << bit)) >> bit;

можно короче :
Код

return (byte>>bit) &1; 

да и остальное можно попроще..

Добавлено через 4 минуты и 58 секунд
однако перестановка битов тут все равно излишняя, так как 
Цитата(Янус @  14.2.2010,  22:36 Найти цитируемый пост)
На вход подается 64-битное двоичное число(записано в символьном массиве

т.е операции идут с байтами, а не битами..

если ж символьный  массив был упомянут для облегчения задания, и нужно все таки оперировать с битами, то вот еще вариантик :
Код

unsigned vec [64] = {0,8,16,24,32,40,48,56,1,9,17,25,33,41,49,57,2,10,18,26,34,42,50,58,3,11,19,27,35,43,51,59,4,12,20,28,36,44,52,60,5,
    13,21,29,37,45,53,61,6,14,22,30,38,46,54,62,7,15,23,31,39,47,55,63};

uint64 encode (uint64 val)
{
  uint64 res = 0;
  for (size_t i=0; i<64; ++ i)
  {
     res |= ( (val >> i) & 1 ) << vec[i];
  }
  return res;
}





--------------------
PM MAIL WWW   Вверх
NewDima
Дата 15.2.2010, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: нет
Всего: 12



mes, да, я действительно делаю через зад =(
PM ICQ   Вверх
NewDima
Дата 15.2.2010, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 922
Регистрация: 20.2.2006
Где: <?here?>

Репутация: нет
Всего: 12



Код

// 1, 2, byteFrom, bitFrom, byteTo, bitTo
inline void _postoposa(char *vf, char *vt, int Bf, int bf, int Bt, int bt) {
    vt[Bt] |= (((vf[Bf] >> bf) & 1) << bt);
}
template<typename T>
//valueTo, valueFrom, bitIndex
inline void movebit(T &vf, T &vt, int bi) {
    _postoposa(reinterpret_cast<char*>(&vf), reinterpret_cast<char*>(&vt), bi/8, bi%8,bi%8+bi/64,bi/8%8);
}

PM ICQ   Вверх
bsa
Дата 15.2.2010, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Код
std::string encode(const std::string &data) {
   static const int ptrdiff_t enc[] = {
       0,8,16,24,32,40,48,56, 1,9,17,25,33,41,49,57,
       2,10,18,26,34,42,50,58, 3,11,19,27,35,43,51,59,
       4,12,20,28,36,44,52,60, 5,13,21,29,37,45,53,61,
       6,14,22,30,38,46,54,62, 7,15,23,31,39,47,55,63
   };
   std::string result(64, '0');
   for(ptrdiff_t i = 0; i != 64; ++i)
      result[enc[i]] = data[i];
   return result;
}


Это сообщение отредактировал(а) bsa - 15.2.2010, 15:51
PM   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1161 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.