Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Циклический сдвиг на PHP
 
 автор: php_user   (14.01.2009 в 19:59)   письмо автору
 
 

Как сделать циклический сдвиг (аналог ROL/ROR) в PHP ?

Делаю так, не работает :(

function ROL($value, $shift)
{
$sft = $shift & 0x1F;
return ($value << $sft) | ($value >> (32 - $sft));
}

  Ответить  
 
 автор: Trianon   (14.01.2009 в 20:11)   письмо автору
 
   для: php_user   (14.01.2009 в 19:59)
 

правый сдвиг знакового целого требует дополнительного маскирования старших разрядов. У Вас этого нет.

  Ответить  
 
 автор: sim5   (14.01.2009 в 20:16)   письмо автору
 
   для: php_user   (14.01.2009 в 19:59)
 

Что не работает? Вообще-то в РНР нет циклического сдвига, так как это делают вышеуказанные команды процессора. Вы об этом?

  Ответить  
 
 автор: Trianon   (14.01.2009 в 20:41)   письмо автору
 
   для: sim5   (14.01.2009 в 20:16)
 

там проще всё. На числах с установленным в 1 старшим битом эта функция будет давать сбой.

Там изменить-то всего чуть.

  Ответить  
 
 автор: sim5   (14.01.2009 в 20:45)   письмо автору
 
   для: Trianon   (14.01.2009 в 20:41)
 

Да я не об этом, я смотрю, что атор хочет добиться аналога команд, а эти команды производят то циклический сдвиг, РНР то ведь этого не делает.

  Ответить  
 
 автор: Trianon   (14.01.2009 в 20:49)   письмо автору
 
   для: sim5   (14.01.2009 в 20:45)
 

Так этого не делает ни php, ни С, ни java . Но это ж не значит что нельзя представить такую операцию.
Скобки в первом посте стоят так, что не позволяют заподозрить автора во мнении что, php эту операцию поддерживает.

  Ответить  
 
 автор: php_user   (14.01.2009 в 20:46)   письмо автору
 
   для: Trianon   (14.01.2009 в 20:41)
 

>> На числах с установленным в 1 старшим битом эта функция будет давать сбой.
>там проще всё. На числах с установленным в 1 старшим битом эта функция будет давать сбой.
>Там изменить-то всего чуть.

И что, надо проверять старший бит? Не хотелось бы с условиями делать...

  Ответить  
 
 автор: Trianon   (14.01.2009 в 20:48)   письмо автору
 
   для: php_user   (14.01.2009 в 20:46)
 

да нет, не надо...

Хотя, нет. пожалуй, условная операция понадобится так или иначе....

  Ответить  
 
 автор: php_user   (14.01.2009 в 20:59)   письмо автору
 
   для: Trianon   (14.01.2009 в 20:48)
 

Спасибо большое!
Все работает!


function ROL($value, $shift)
{
$sft = $shift & 0x1F; // чтобы учитывались только младшие 5 разрядов
return ($value << $sft) | (($value >> (32 - $sft)) & ((1 << (31 & $sft)) - 1)) ;
}

  Ответить  
 
 автор: Trianon   (14.01.2009 в 21:00)   письмо автору
 
   для: php_user   (14.01.2009 в 20:59)
 

Не работает.
При $sft = 31 будет сбой.
А может не будет. Выход за разрядную сетку будет точно.

  Ответить  
 
 автор: php_user   (14.01.2009 в 21:19)   письмо автору
 
   для: Trianon   (14.01.2009 в 21:00)
 

Может делать выборку маски из массива ?

  Ответить  
 
 автор: Trianon   (14.01.2009 в 21:25)   письмо автору
 
   для: php_user   (14.01.2009 в 21:19)
 

на ассемблере вариант с векторизацией был бы самым быстрым. На php - сомнительно.
((((1<<($sft -1))-1)<<1)|1)
при sft = 0 вообще аргумент не нужно дергать.

надо измерять быстродействие и выбирать самый шустрый вариант.

И кстати, стоит убедиться что для 64-разрядного php еще чего не выползет.

  Ответить  
 
 автор: php_user   (14.01.2009 в 21:38)   письмо автору
 
   для: Trianon   (14.01.2009 в 21:25)
 

для проверки сделал так
function ROL($value, $shift)
{
$sft = $shift & 0x1F;
if ($sft == 31) { echo $sft; }
return ($value << $sft) | (($value >> (32 - $sft)) & ((1 << (31&$sft)) - 1) ) ;
}

В процессе обработки масива из ~4000 32-хразрядных элементов сдвиг на 31 проскакивал несколько десятков раз. Тем не менее все обработалось правильно...
С вариантом ((((1<<($sft -1))-1)<<1)|1) так же...

Для сравнения по быстродействию сделал
echo microtime() . "<br>\r\n";
$x = 0x12345678;
$y = 0;
for ($i=0; $i<1000000; $i++)
{
$y = $y | ROL($x, $i);
}
echo microtime() . "<br>\r\n";
die("result = " . $y);

1-й, 2-й варианты и вариант с массивом (глобальным) выполняются примерно одинаково за 4 сек.

  Ответить  
 
 автор: php_user   (14.01.2009 в 20:44)   письмо автору
 
   для: sim5   (14.01.2009 в 20:16)
 

В том-то и дело, что нету :( Стало быть надо сделать функцию аналог...

Как и сказал Trianon, дело оказалось в маскировании старших разрядов при сдвиге вправо, сейчас разбираюсь с этим...

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования