Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, Кодт, Вы писали:
К>за O(N)
ME>[]
К>За O(log N) — двоичный поиск: x<>2^16? x<>2^8? и так далее.
ME>[]
ME>Я видел код (буквально пять строчек), который это делает без цикла за O(1). Вот только ссылку никак не могу найти
а идею не помните?
Re[4]: как узнать номер n-го установленного (1) бита внутри
Здравствуйте, Sergeem, Вы писали:
S>Здравствуйте, MaximE, Вы писали:
ME>Я видел код (буквально пять строчек), который это делает без цикла за O(1). Вот только ссылку никак не могу найти
S>
S>int what_bit(unsigned long x)
S>{
S> if(x==0) return -1; // no bits
S> if (x & (x-1)) return -2; // multiple bits
S> return int(log(x)/log(2)); // :shuffle: ;)
S>}
S>
S>Как бы логарифм по основанию два извлечь без плавающей точки и за О(1)?
может я не совсем правильно выразился, перефразирую вопрос:
есть некий long
в нем установлены в разных местах битики в 1, остальные 0.
в этой последовательности необходимо найти n-й по счету установленный в 1 бит. местоположение его конечно имеет номер не меньше n.
пример:
для 1001110010... и n=4, ответ будет = 6
Re[3]: как узнать номер n-го установленного (1) бита внутри
Здравствуйте, WeCom, Вы писали:
WC>Что сказано в сабже? — "как узнать номер n-го установленного (1) бита внутри long?" WC>Т.е. есть какое-то число (long). У него установлено несколько битов (в 1). Надо узнать номер (позицию) энного. Для n=1, задача в нахождении позиции самого правого единичного бита, для n=2 — позиции следующего единичного после самого правого, и т.д. А вы какую задачу решаете? — Найти позицию единственного единичного бита в long'е? Так это другая задача.
МОЛОТЦА, я это и имел ввиду и эту задачу и надо решить, жеоательно, если руку приложат на ассемблере
Re[4]: как узнать номер n-го установленного (1) бита внутри
Здравствуйте, Dmitry Kukushkin, Вы писали:
DK>Здравствуйте, WeCom, Вы писали:
WC>Неверно. Например, GetBitPos(0xF,3) должен вернуть 2, а возвращает -1. Возможно, n и tested перепутаны местами, но GetBitPos(3,0xF) также возвращает -1.
DK>Извиняюсь... DK>Аргументы действительно перепутаны и в цикле там малек не то... DK>Ну вот — для ясности:
DK>
DK>char GetBitPos(long data, long n)
DK>{
DK> int i;
DK> char pos;
DK> for(i = 0; i < n && data != 0; i++)
DK> {
DK> __asm
DK> {
DK> bsf eax, data
DK> btr data, eax
DK> mov pos, al
DK> }
DK> }
DK> return i == n ? pos : -1;
DK>}
DK>
МОЛОТЦА — САМЫЙ ЛУЧШИЙ ОТВЕТ МАКСИМАЛЬНЫЙ БАЛ
позволил себе несколько изменить код (если верить TrueTime от Numega, работает намного быстрее)
char GetBitPos1(long data, long n)
{
char i;
char pos;
__asm
{
mov ecx, n
m:
bsf eax, data
btr data, eax
jz end
mov pos, al
loop m
end:
cmp ecx, 0
je m2
mov pos, 0
m2:
}
return pos ;
}
Re: как узнать номер n-го установленного (1) бита внутри lon
Здравствуйте, ilnar, Вы писали:
I>сабж. I>как узнать номер n-го установленного (1) бита внутри long? I>не ли какой-либо команды процессора или какой-нибудь код для С/С++
#include"iostream.h"// ВАРИАНТ1int GetBitPos( int arg, int n )
{
// Простой вариант. Сложность - nint pos = 0;
int cnt;
for( cnt =0; cnt<n && pos<32; pos++){
cnt += (arg>>31) & 1;
arg <<= 1;
}
if( cnt<n )
return -1;
else
return pos;
}
// ВАРИАНТ2int GetBitPos2( unsigned int arg, int n )
{
// Базируется на алгоритме подсчета установленных битов в слове,
// было то ли в алгоритмах, то ли в этюдникеunsigned int n1 = ((arg& 0xAAAAAAAA) >> 1 ) + (arg& 0x55555555);
unsigned int n2 = ((n1 & 0xCCCCCCCC) >> 2 ) + (n1 & 0x33333333);
unsigned int n3 = ((n2 & 0xF0F0F0F0) >> 4 ) + (n2 & 0x0F0F0F0F);
unsigned int n4 = ((n3 & 0xFF00FF00) >> 8 ) + (n3 & 0x00FF00FF);
unsigned int n5 = ((n4 & 0xFFFF0000) >> 16) + (n4 & 0x0000FFFF);
// n5 - общее кол-во установленных битовif (n5 < n)
return -1;
if (!n)
return 0;
// Ищем спускаясь по двоичному дереву. Сложность - log(n)int pos;
unsigned int mask = 0xFFFF0000;
int leftHalf = (n4 & mask) >> 16;
if ( n > leftHalf){
pos = 16; // Вправо
n -= leftHalf;
mask >>= 16;
}
else{
pos = 0; // Влево
}
mask &= 0xFF00FF00;
leftHalf = (n3 & mask) >> (32-pos-8);
if ( n > leftHalf){
pos += 8; // Вправо
n -= leftHalf;
mask >>= 8;
}
mask &= 0xF0F0F0F0;
leftHalf = (n2 & mask) >> (32-pos-4);
if ( n > leftHalf){
pos += 4; // Вправо
n -= leftHalf;
mask >>= 4;
}
mask &= 0xCCCCCCCC;
leftHalf = (n1 & mask) >> (32-pos-2);
if ( n > leftHalf){
pos += 2; // Вправо
n -= leftHalf;
mask >>= 2;
}
mask &= 0xAAAAAAAA;
leftHalf = (arg & mask) >> (32-pos-1);
if ( n > leftHalf){
pos += 1; // Вправо
n -= leftHalf;
mask >>= 1;
}
return pos+1;
}
// ТЕСТint main(int argc, char* argv[])
{
printf("Hello World!\n");
cout << GetBitPos ( 0, 0 ) << "\n";
cout << GetBitPos ( 0xFF00FF00, 1 ) << "\n";
cout << GetBitPos ( 0xFF00FF00, 3 ) << "\n";
cout << GetBitPos ( 0xFF00FF00, 9 ) << "\n";
cout << GetBitPos ( 0xFF00FF00, 20) << "\n";
cout << GetBitPos2( 0, 0 ) << "\n";
cout << GetBitPos2( 0xFF00FF00, 1 ) << "\n";
cout << GetBitPos2( 0xFF00FF00, 3 ) << "\n";
cout << GetBitPos2( 0xFF00FF00, 9 ) << "\n";
cout << GetBitPos2( 0xFF00FF00, 20) << "\n";
flush(cout);
unsigned int i;
int r=0;
for(i=0;i<10000000;i++){
r+=GetBitPos( i, i % 16);
}
cout << r << "\n";
flush(cout);
r = 0;
for(i=0;i<10000000;i++){
r+=GetBitPos2( i, i % 16);
}
cout << r << "\n";
flush(cout);
return 0;
}
Работает! Самое смешное, второй вариант действительно быстрее (int32, x86, vc60) % на 30. ilnar, с тебя пузырь! Вообще то, если использовать встроенную инструкцию поиска первого бита, будет конечно быстрее. Зато так переносимо. И соответствует форуму. И вообще круче.
Re[2]: как узнать номер n-го установленного (1) бита внутри
Здравствуйте, Les, Вы писали:
Les>Здравствуйте, ilnar, Вы писали: Les>Работает! Самое смешное, второй вариант действительно быстрее (int32, x86, vc60) % на 30. ilnar, с тебя пузырь! Вообще то, если использовать встроенную инструкцию поиска первого бита, будет конечно быстрее. Зато так переносимо. И соответствует форуму. И вообще круче.
а мне совсем не смешно от того, что операции С/С++ намного урезают операции процессора, иногда смотришь команды процессора и видишь, что то, что я пишу на С — на самом-то деле выполняется одной операцией процессора.
Соответствие форуму у ассемблера тоже есть по двум причинам:
— хотел получиь лаконичный ответ на С/С++
— ассемблерные вставки описаны в этих языках
кстати, gcc уже поддерживает формат записи ассемблера как у майкрасофта,
а переносимость на другие аппаратные платформы и не собираюсь
Re: как узнать номер n-го установленного (1) бита внутри lon
Здравствуйте, ilnar, Вы писали:
I>сабж. I>как узнать номер n-го установленного (1) бита внутри long? I>не ли какой-либо команды процессора или какой-нибудь код для С/С++
для этого есть шаблон std::bitset.
Re[3]: как узнать номер n-го установленного (1) бита внутри
...
I>кстати, gcc уже поддерживает формат записи ассемблера как у майкрасофта, I>а переносимость на другие аппаратные платформы и не собираюсь
не зарекайтесь!
завтра (вспомните закон Мура) выйдет новый супер-пупер 137-битный процессор
у которого родной istruction set будет в 10 раз быстрее чем ваши х86 ассемблерные
вставки. Что, будете каждый раз код переписывать?
Serge.
Hасколько проще была бы жизнь, если бы она была в исходниках.
Re[4]: как узнать номер n-го установленного (1) бита внутри
Здравствуйте, Sergeem, Вы писали:
S>Здравствуйте, ilnar, Вы писали:
S>...
I>кстати, gcc уже поддерживает формат записи ассемблера как у майкрасофта, I>а переносимость на другие аппаратные платформы и не собираюсь
S>не зарекайтесь! S>завтра (вспомните закон Мура) выйдет новый супер-пупер 137-битный процессор S>у которого родной istruction set будет в 10 раз быстрее чем ваши х86 ассемблерные S>вставки. Что, будете каждый раз код переписывать?
скжау 2 вещи:
1. языки высокого уровня всегда урезают возможности процессора для реализации какой-либо операции.
2. я найду время переписать код в 10 строк, зато программа будет быстрее намного работать
Re: как узнать номер n-го установленного (1) бита внутри lon
Здравствуйте, ilnar, Вы писали:
I>сабж. I>как узнать номер n-го установленного (1) бита внутри long? I>не ли какой-либо команды процессора или какой-нибудь код для С/С++
Так вот, надо создать базу данных всех чисел типа long где для каждого бита каждого числа будет храниться значение, указывающее, установлен он в 1 или в 0. Теперь при необходимости можно выполнить SQL-запрос и получить полную информацию о каждом бите нужного числа
Re[2]: как узнать номер n-го установленного (1) бита внутри
От:
Аноним
Дата:
30.04.03 11:58
Оценка:
Здравствуйте, impaler, Вы писали:
I>Так вот, надо создать базу данных всех чисел типа long где для каждого бита каждого числа будет храниться значение, указывающее, установлен он в 1 или в 0. Теперь при необходимости можно выполнить SQL-запрос и получить полную информацию о каждом бите нужного числа
Что ж, это максимально гибко. А при необходимости битовое представление чисел можно будет даже и менять!
Re[2]: как узнать номер n-го установленного (1) бита внутри
Здравствуйте, skyline, Вы писали:
S>Кстати, что за зверь boost::dynamic_bitset ?
Description
The dynamic_bitset class represents a set of bits. It provides accesses to the value of individual bits via an operator[] and provides all of the bitwise operators that one can apply to builtin integers, such as operator& and operator<<. The number of bits in the set is specified at runtime via a parameter to the constructor of the dynamic_bitset.
The dynamic_bitset class is nearly identical to the std::bitset class. The difference is that the size of the dynamic_bitset (the number of bits) is specified at run-time during the construction of a dynamic_bitset object, whereas the size of a std::bitset is specified at compile-time through an integer template parameter.
The main problem that dynamic_bitset is designed to solve is that of representing a subset of a finite set. Each bit represents whether an element of the finite set is in the subset or not. As such the bitwise operations of dynamic_bitset, such as operator& and operator|, correspond to set operations, such as intersection and union.
Re[5]: как узнать номер n-го установленного (1) бита внутри
Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, skyline, Вы писали:
S>Кстати, что за зверь boost::dynamic_bitset ?
Я хотел спросить, это что: приблуда к C или приблуда к какому-то компилятору — а то у меня в MSDN нет ничего на эту тему. Судя по описанию, это неплохой механизм.
If the milk turns out to be sour,
I ain't the kind of pussy to drink it
Re[6]: как узнать номер n-го установленного (1) бита внутри
Здравствуйте, skyline, Вы писали:
S>Здравствуйте, MaximE, Вы писали:
ME>>Здравствуйте, skyline, Вы писали:
S>>Кстати, что за зверь boost::dynamic_bitset ?
S>Я хотел спросить, это что: приблуда к C или приблуда к какому-то компилятору — а то у меня в MSDN нет ничего на эту тему. Судя по описанию, это неплохой механизм.
Это набор всяких разных дополнительных библиотек к C++, обладает довольно богатыми возможностями (кстати, может частично войдет в будущий стандарт STL).