Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2015.09.10;
Скачать: [xml.tar.bz2];

Вниз

Задачка::Проверка бита   Найти похожие ветки 

 
Dimka Maslov ©   (2014-10-14 11:07) [0]

Дано: имеется целое число (n). Известно, что в нём установлен только один бит, остальные нули.
Требуется установить номер этого бита (i).

Возможные решения:
1) for (i = 0; n && (n & 1) == 0; n>>=1, i++);
2) i = (int)log2((double)n);
3) тупо через switch

Какие ещё могут быть варианты?


 
Romkin ©   (2014-10-14 11:11) [1]

Массив.
Вообще зависит от разрядности этого самого числа.


 
manaka ©   (2014-10-14 11:16) [2]


> Известно, что в нём установлен только один бит, остальные
> нули


Значит число есть степень 2
Номер бита=степень+1


 
Юрий Зотов ©   (2014-10-14 11:22) [3]

2^x = n

x = Log2(n)


 
manaka ©   (2014-10-14 11:23) [4]

i:=1;
while n<>1 do begin
 n=n/2;
 i=i+1;
end;


))))))


 
MBo ©   (2014-10-14 11:24) [5]

Ассемблер, BSR/BSF

Бинарный поиск

 if (x and $FFFF0000)>0 then Index := Index+16;
 и т.п.


 
oldman ©   (2014-10-14 11:24) [6]


> Юрий Зотов ©   (14.10.14 11:22) [3]
> x = Log2(n)


x=log2(n)+1


 
Юрий Зотов ©   (2014-10-14 11:33) [7]

> oldman ©   (14.10.14 11:24) [6]

Это зависит от соглашения о нумерации. Если оно не оговорено, то в мире IT биты принято нумеровать, начиная с нуля.


 
Юрий Зотов ©   (2014-10-14 11:35) [8]

Кто тег не закрыл?

Теперь закрыт.


 
Dimka Maslov ©   (2014-10-14 11:35) [9]


> Romkin ©   (14.10.14 11:11) [1]


Для 64 бит массив будет ооооооооооочень большим


> Юрий Зотов ©   (14.10.14 11:22) [3]


Вариант 2 получается


> manaka ©   (14.10.14 11:23) [4]


Вариант 1 получается


> MBo ©   (14.10.14 11:24) [5]


чё-то не понял


> oldman ©   (14.10.14 11:24) [6]


log2(1) = 0,  а биты нумеруются от 0 до 31. так что всё правильно


 
MBo ©   (2014-10-14 11:35) [10]


незакрытый тег, видимо, я оставил.

Погуглил - без ветвлений есть метод:

var
 i, x: integer;
 table: array[0..31] of Integer;
begin
 for i := 0 to 31 do //инициализация, метод de Brujin
   table[ ( $077CB531 * ( 1 shl i ) ) shr 27 ]  := i;

 x := 1 shl 17;
 Caption := IntToStr(table[(x * $077CB531) shr 27]);


 
MBo ©   (2014-10-14 11:37) [11]

>чё-то не понял
Не понял про ассемблерные команды, или про бинарный поиск?


 
Dimka Maslov ©   (2014-10-14 11:39) [12]

Про бинарный поиск


 
MBo ©   (2014-10-14 11:46) [13]


r:=0; //индекс единичного бита будет тут
if (x and $FFFF0000)>0 then r:=r+16; // бит в старшем слове
if (x and $FF00FF00)>0 then r:=r+8;  // бит в старшем байте одного из слов
if (x and $F0F0F0F0)>0 then r:=r+4;  // бит в старшем ниббле одного из байтов
if (x and $CCCCCCCC)>0 then r:=r+2;  //бит в одно из старших битов ниббла
if (x and $AAAAAAAA)>0 then r:=r+1;   //бит на нечетном месте  $AA = bin10101010


 
Дмитрий С ©   (2014-10-14 12:42) [14]

Неужели банальную подсветку так сложно сделать с первого раза? :))


 
Inovet ©   (2014-10-14 15:59) [15]

> [14] Дмитрий С ©   (14.10.14 12:42)

Сделай


 
Inovet ©   (2014-10-14 15:59) [16]

> [9] Dimka Maslov ©   (14.10.14 11:35)
> Для 64 бит массив будет ооооооооооочень большим

64 элемента и будет по условию задачи.


 
Rouse_ ©   (2014-10-14 18:05) [17]

Самое быстрое, конечно BSR, если задача на оптимизацию по скорости


 
MBo ©   (2014-10-14 18:37) [18]


> Самое быстрое, конечно BSR, если задача на оптимизацию по
> скорости

Не факт. Оно, кажется, конвейеры с панталыку сбивает.
Я 4 метода испытал на старом Athlon - с магическим умножением, бинарный поиск, и BSR дают примерно одно и то же время, а сдвиг числа вправо, пока бит не найдется - втрое большее на таком тесте:
for k := 1 to 100000000 do begin
   i := 1 shl (k mod 32);
   l := l + BitIndex(i);
 end;


 
Dimka Maslov ©   (2014-10-14 19:20) [19]


> Самое быстрое, конечно BSR, если задача на оптимизацию по
> скорости


Проблема в том, что на 64 битах злые вредоносные существа не дают прямого доступа к ассемблеру. Вот и приходится извращаться.


 
Pavia ©   (2014-10-14 19:21) [20]


> Не факт. Оно, кажется, конвейеры с панталыку сбивает.

Только если на микрокоде сделана.


 
Rouse_ ©   (2014-10-14 19:24) [21]


> MBo ©   (14.10.14 18:37) [18]
> Не факт. Оно, кажется, конвейеры с панталыку сбивает.

uses
 Windows;

function GetIndexBsr(Value: DWORD): Byte; assembler;
asm
 bsr eax, eax
end;

function GetIndexMBo(Value: DWORD): Byte;
begin
 Result := 0; //индекс единичного бита будет тут
 if (Value and $FFFF0000) > 0 then Result := Result + 16; // бит в старшем слове
 if (Value and $FF00FF00) > 0 then Result := Result + 8;  // бит в старшем байте одного из слов
 if (Value and $F0F0F0F0) > 0 then Result := Result + 4;  // бит в старшем ниббле одного из байтов
 if (Value and $CCCCCCCC) > 0 then Result := Result + 2;  //бит в одно из старших битов ниббла
 if (Value and $AAAAAAAA) > 0 then Result := Result + 1;   //бит на нечетном месте  $AA = bin10101010
end;

var
 I: Integer;
 S: DWORD;
begin
 Randomize;
 S := GetTickCount;
 for I := 0 to 100000000 do
   GetIndexBsr(I);
 Writeln(GetTickCount - S);
 S := GetTickCount;
 for I := 0 to 100000000 do
   GetIndexMBo(I);
 Writeln(GetTickCount - S);
 Readln;
end.


265
1778


 
Rouse_ ©   (2014-10-14 19:27) [22]

PS^ тем более что GetIndexMBo(6) = 3.
Или я не тот алгритм взял?


 
Rouse_ ©   (2014-10-14 19:28) [23]


> Dimka Maslov ©   (14.10.14 19:20) [19]
> Проблема в том, что на 64 битах злые вредоносные существа
> не дают прямого доступа к ассемблеру. Вот и приходится извращаться.

Приведенный в [21] код достаточно успешно компилируется и работает в 64 битах :)


 
Rouse_ ©   (2014-10-14 19:34) [24]

Может и не в тему, но тоже хочу задачку для разминки мозга подкинуть.
Дан ряд чисел от единицы до N (к примеру если N = 6, то ряд выглядит как 1,2,3,4,5,6).
Задача: написать функцию возвращающую сумму всех чисел ряда. (При N = 6, результат 21)
Ограничения - функция не должна использовать цикл или рекурсию.


 
Dimka Maslov ©   (2014-10-14 19:35) [25]


> Приведенный в [21] код достаточно успешно компилируется
> и работает в 64 битах :)


Смотря каких. Маздайный С++ говорит, что
error C4235: nonstandard extension used : "__asm" keyword not supported on this architecture

И всё. Приплыли.


 
Rouse_ ©   (2014-10-14 19:38) [26]

Под арму чтоль компилишь?


 
Rouse_ ©   (2014-10-14 19:39) [27]

под 64 битами все пахет в MS VC++ 2010


 
MBo ©   (2014-10-14 19:39) [28]


> Или я не тот алгритм взял?

Тот. Входные данные некорректные - один бит должен быть установлен, я выделение младшего бита убрал. Это может повлиять на ветвления, но не настолько радикально. Видимо, другая архитектура ядра процессора сказывается. Вот мой полный тест.


var
 i, k, l: Integer;
 table: array[0..31] of Integer;
 t: DWord;

function BitIndexBSR(Value: Integer): Integer;
asm
  BSR   EAX,EAX
end;

function BitIndexDeBruijn(Value: Integer): Integer;
begin
 Result := table[(Value * $077CB531) shr 27];
end;

function BitIndexSHR(Value: Integer): Integer;
begin
 Result :=0;
 while (Value and 1) = 0 do begin
   Inc(Result);
   Value := Value shr 1;
 end;
end;

function BitIndexBinS(Value: Integer): Integer;
begin
 result:=0; //индекс единичного бита будет тут
 if (Value and $FFFF0000)<>0 then result:=result+16; // бит в старшем слове
 if (Value and $FF00FF00)<>0 then result:=result+8;  // бит в старшем байте одного из слов
 if (Value and $F0F0F0F0)<>0 then result:=result+4;  // бит в старшем ниббле одного из байтов
 if (Value and $CCCCCCCC)<>0 then result:=result+2;  //бит в одно из старших битов ниббла
 if (Value and $AAAAAAAA)<>0 then result:=result+1;   //бит на нечетном месте  $AA = bin10101010
end;

begin
 l := 0;
 for i := 0 to 31 do //инициализация, метод de Brujin
   table[ ( $077CB531 * ( 1 shl i ) ) shr 27 ]  := i;

 t := GetTickCount;
 for k := 1 to 100000000 do begin
   i := 1 shl (k mod 32);
   l := l + BitIndexBSR(i);
 end;
 Memo1.Lines.Add(Format("BSR %d", [GetTickCount- t]));

 t := GetTickCount;
 for k := 1 to 100000000 do begin
   i := 1 shl (k mod 32);
   l := l + BitIndexDeBruijn(i);
 end;
 Memo1.Lines.Add(Format("DeBruijn %d", [GetTickCount- t]));

 t := GetTickCount;
 for k := 1 to 100000000 do begin
   i := 1 shl (k mod 32);
   l := l + BitIndexBinS(i);
 end;
 Memo1.Lines.Add(Format("BinSearch %d", [GetTickCount- t]));

 t := GetTickCount;
 for k := 1 to 100000000 do begin
   i := 1 shl (k mod 32);
   l := l + BitIndexSHR(i);
 end;
 Memo1.Lines.Add(Format("SHR %d", [GetTickCount- t]));


Athlon 3500+
BSR 1422
DeBruijn 1578
BinSearch 1438
SHR 6422


 
Dimka Maslov ©   (2014-10-14 19:40) [29]

Нет x64 под Венду. Не даёт. А если как в спраке сказано, понизить уровень до ворнинга, то говорит, что bsr и eax неизвестные идентификаторы, однако...


 
MBo ©   (2014-10-14 19:41) [30]

А вот магические числа deBruijn для 64 бит:
Table[(uint64_t)(val * 0x022fdd63cc95386dull) >> 58];


 
Rouse_ ©   (2014-10-14 19:48) [31]


> MBo ©   (14.10.14 19:39) [28]

Ну как я и говорил изначально - BSR самый шустрый по скорости :)


> Dimka Maslov ©   (14.10.14 19:40) [29]
> Нет x64 под Венду. Не даёт.

Ты че там такое компиляш?
Давай демку архивом, завтра гляну.


 
Ega23 ©   (2014-10-14 19:57) [32]


> Rouse_ ©   (14.10.14 19:34) [24]
>
> Может и не в тему, но тоже хочу задачку для разминки мозга
> подкинуть.
> Дан ряд чисел от единицы до N (к примеру если N = 6, то
> ряд выглядит как 1,2,3,4,5,6).
> Задача: написать функцию возвращающую сумму всех чисел ряда.
>  (При N = 6, результат 21)
> Ограничения - функция не должна использовать цикл или рекурсию.
>


Result := (((N + 1) * N) shr 1);


 
Dimka Maslov ©   (2014-10-14 20:00) [33]

#define BIT0    0x01
#define BIT1    0x02
#define BIT2    0x04
#define BIT3    0x08
#define BIT4    0x10
#define BIT5    0x20
#define BIT6    0x40
#define BIT7    0x80

long BitIndex(long N)
{
__asm
{
mov eax, N
       bsr eax, eax
}
}

Microsoft Visual Studio 2013 простое консольное приложение 64 бита. Ассемблер более не дозволен.


 
MBo ©   (2014-10-14 20:03) [34]


> Microsoft Visual Studio 2013 простое консольное приложение
> 64 бита. Ассемблер более не дозволен.


Интринсики же есть _BitScanReverse64


 
Юрий Зотов ©   (2014-10-14 20:04) [35]

А логарифм как, по скорости?


 
Rouse_ ©   (2014-10-14 20:10) [36]


> Ega23 ©   (14.10.14 19:57) [32]

Гаусс? Молоток, зарраза :)


 
Inovet ©   (2014-10-14 20:10) [37]

> [24] Rouse_ ©   (14.10.14 19:34)
> Задача: написать функцию возвращающую сумму всех чисел ряда. При N = 6, результат 21)

Это что ли?
Для нечётных Н*Н/2
для чётных Н*(Н+1)/2


 
Kerk ©   (2014-10-14 20:11) [38]


> Дан ряд чисел от единицы до N

https://ru.wikipedia.org/wiki/%C0%F0%E8%F4%EC%E5%F2%E8%F7%E5%F1%EA%E0%FF_%EF%F0%EE%E3%F0%E5%F1%F1%E8%FF#.D0.A1.D1.83.D0.BC.D0.BC.D0.B0_.D0.BF.D0.B5.D1.80.D0.B2.D1.8B.D1.85_.D1.87.D0 .BB.D0.B5.D0.BD.D0.BE.D0.B2_.D0.B0.D1.80.D0.B8.D1.84.D0.BC.D0.B5.D1.82.D0.B8.D1. 87.D0.B5.D1.81.D0.BA.D0.BE.D0.B9_.D0.BF.D1.80.D0.BE.D0.B3.D1.80.D0.B5.D1.81.D1.8 1.D0.B8.D0.B8

?


 
Rouse_ ©   (2014-10-14 20:12) [39]


> Inovet ©   (14.10.14 20:10) [37]

Угу, оно... забыл что вы тут все умные, каюсь. Задачка - так себе :)


 
Rouse_ ©   (2014-10-14 20:14) [40]

Есть еще один вариант не методом Гаусса решается, но в принципе - задача решена :)



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2015.09.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.042 c
2-1397989657
vini
2014-04-20 14:27
2015.09.10
Как изменить размер bitmap


15-1415815791
alexdn
2014-11-12 21:09
2015.09.10
Вопрос по wordpress


2-1392837011
alexdn
2014-02-19 23:10
2015.09.10
Узнать ip


15-1414182614
Юрий
2014-10-25 00:30
2015.09.10
С днем рождения ! 25 октября 2014 суббота


15-1416469605
alexdn
2014-11-20 10:46
2015.09.10
Фотохостинг





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский