Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Как вырезать биты из байта?

Автор: ONIX2
Дата сообщения: 10.10.2006 16:01
Друзья, помогите пожалуйста:

Имеется две 32-х разрядные переменные X и Y такие, что X and Y = 0, то есть единичные биты не пересекаются. Необходимо вырезать в переменной X биты, помеченные единичками в Y со сдвигом.

Например:

X=000100110001
Y=000001000100
R=000001100100

Это необходимо для шахматной программы, где такое действие выполняется примерно 2 млн раз/сек. Как сделать с массивом - понятно, но надо, чтобы было большое быстродействие, поможете?
Автор: dyr farot
Дата сообщения: 10.10.2006 16:32
что значит "вырезать со сдвигом"? из приведенного примера это не видно.
в любом случае используй битовые сдвиги
Автор: OdesitVadim
Дата сообщения: 10.10.2006 16:33
не слишком понятно, что ты хочеш сделать. Куда и как резать.
Но могу сказать, что для сдвига тебе поможут операторы shl и shr - сдвиг влево и вправо соответственно на указаное кол-во бит.
типа
x:=2;
x:=x shl 2;
тепере x=8
Автор: ONIX2
Дата сообщения: 10.10.2006 17:07
Попробую пояснить на лучшем примере:

X=000011000101010
Y=000000100000000
R=000011001010100

Но в Y может быть установлен и не один бит. Сдвиг влево (хотя в самой задаче сущность не меняется)
Автор: f_serg
Дата сообщения: 11.10.2006 07:59
ONIX2

Код: unsigned int f(unsigned int X, unsigned int Y)
{
unsigned int R = 0;
int ix, iy;

for (ix = iy = 31; ix >= 0; ix--) { /* Бежим по битам, начиная со старшего */
    if (X & (1 << ix)) { /* Бит ix в X установлен? */
        R |= (1 << iy); /* Устанавливаем единицу в результате в бите iy */
        iy--; /* X & Y == 0, значит сдвига не будет */
    } else
        if (!(Y & (1 << ix))) /* Бит ix в Y не установлен? */
            iy--; /* значит сдвига не будет */
/* Бит ix в Y установлен. Не меняем iy, сдвиг происходит автоматически */
}

return R;
}
Автор: ONIX2
Дата сообщения: 11.10.2006 13:25

Цитата:
Все-таки R=000101100100   Разбирайся.


Извиняюсь, все правильно вы уточнили, опечатался
Просто программа на Delphi, а там одно слово только "оптимизация"
Автор: Ulysses4ever
Дата сообщения: 11.10.2006 19:43
По быстродействию точно не лучший вариант: вместо того, чтобы каждый раз единицу тягать на энное количество бит, лучше запоминать результат сдвига - тогда на каждлм шаге цикла только на 1 бит сдвигаться...

Добавлено:
Вообще, какое-то подозрительное решение. Я не пойму, почему в первой ветке if условие на биты в X, когда нам Y указывает, будет сдвиг или не будет.

Если не сложно, вы бы привели тестовую программку (там очень хорошо было бы реализовать печать двоичного представления). И ее результаты, соответственно.
Автор: Qraizer
Дата сообщения: 11.10.2006 21:26
А такое решение не пропрёт?
Код: #include <iostream>
#include <bitset>
#include "bin.h"

int main()
{
int X = BIN32(00000000, 00000000, 00000001, 00110001);
int Y = BIN32(00000000, 00000000, 00000000, 01000100);

std::cout << "In begin : X is " << std::bitset<32>(X).to_string<
char,
std::char_traits<char>,
std::allocator <char>
>() << "\n"
<< " Y is " << std::bitset<32>(X).to_string<
char,
std::char_traits<char>,
std::allocator <char>
>() << "\n";
// Это присказка, а сказка вот:
while(Y!=0)
{
int temp = (-Y & Y) - 1;

X = X & ~temp | ((X & temp) << 1);
Y^= temp+1;
}
// Проверка результатов
std::cout << "In result: X is " << std::bitset<32>(X).to_string<
char,
std::char_traits<char>,
std::allocator <char>
>() << std::endl;
}
Автор: f_serg
Дата сообщения: 12.10.2006 07:48
Ulysses4ever

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

Один такт процессора. Если не нравится, можно сделать массив из 32-х констант
{ 1, 2, 4, 8, ... } и работать с ним.

Цитата:
почему в первой ветке if условие на биты в X, когда нам Y указывает, будет сдвиг или не будет.

Эти единицы надо переносить в результат. А т.к. X and Y равно 0, то в Y на этой позиции точно не будет единицы.

Цитата:
Если не сложно, вы бы привели тестовую программку

Да проверял я. На двух примерах. Которые привел ONIX2.


Добавлено:
А вообще, конечно, для быстродействия надо чтобы кто-нибудь на ассемблере написал функцию, потом это объектник цеплять к программе.
Автор: basilevs
Дата сообщения: 12.10.2006 12:13
я бы предложил простой, но внятный путь
unsigned int f(unsigned int X, unsigned int Y)
{
unsigned int R = X;
unsigned int ix, iy;
iy=Y;ix=((-iy)&iy);
while (ix != 0) { /* Бежим по ненулевым битам Y , начиная с младшего*/
R= R+ R&(ix-1);iy=iy-ix;ix=(-iy)&iy;};
return R;
}
Полагаю, объяснять не нужно, но всё же - удвоение остатка - как метод схлопывания.
для x86 ASM оптимизированный код, без учета вызовов и передачи параметров,
может выглядет примерно так
[pre]
MOV    EAX,X
MOV    EBX,Y
@loop
MOV    ECX,EBX
NEG    ECX
AND    ECX,EBX
JZ    @end
SUB     EBX,ECX
DEC    ECX
AND    ECX,EAX
ADD    EAX,ECX
JNZ    @loop
@end
MOV    result,EAX
[/pre]
Автор: ONIX2
Дата сообщения: 13.10.2006 13:21
Друзья, спасибо вам за ответы!

В принципе, ассемблерный и сиш9ный варианты одинаково быстро работают, а мне и будет достаточно.

СПАСИБО!

Страницы: 1

Предыдущая тема: Delphi, компонент (библиотека?) для работы с USB


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.