Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Сдвиги. Как с ними работать?

249
31 марта 2005 года
DissDoc
639 / / 01.10.2004
У меня 4 вопроса по теме сдвигов. Как при помощи сдвигов:
1. поделить число на 2;
2. умножить число на 2;
3. возвеси во вторую(третью и т.д.) степень;
4. извлечь корень (квадратный, кубический и т.д.).
2
31 марта 2005 года
squirL
5.6K / / 13.08.2003
Цитата:
Originally posted by DissDoc
У меня 4 вопроса по теме сдвигов. Как при помощи сдвигов:
1. поделить число на 2;
2. умножить число на 2;
3. возвеси во вторую(третью и т.д.) степень;
4. извлечь корень (квадратный, кубический и т.д.).



хм... а причем тут VC++? ну ладно...
1. сдвинуть биты числа на один разряд вправо

6/2 = 3
110/10 = 011

2. сдвинуть биты числа на один разряд влево

5*2=10
101*10=1010

425
31 марта 2005 года
sq_deep
498 / / 18.02.2005
Цитата:
Originally posted by DissDoc
У меня 4 вопроса по теме сдвигов. Как при помощи сдвигов:
1. поделить число на 2;
2. умножить число на 2;
3. возвеси во вторую(третью и т.д.) степень;
4. извлечь корень (квадратный, кубический и т.д.).


1, 2: см. ответ squirLа.
3, 4: сдвигами не делаются.

249
31 марта 2005 года
DissDoc
639 / / 01.10.2004
Цитата:
Originally posted by squirL
хм... а причем тут VC++? ну ладно...
1. сдвинуть биты числа на один разряд вправо

6/2 = 3
110/10 = 011

2. сдвинуть биты числа на один разряд влево

5*2=10
101*10=1010



Не-не-не! я хотел узнать синтаксис сдвигов на С++.. Сам принцип сдвигов я знаю.. а как реализовать их в с++?

2
31 марта 2005 года
squirL
5.6K / / 13.08.2003
Цитата:
Originally posted by DissDoc
Не-не-не! я хотел узнать синтаксис сдвигов на С++.. Сам принцип сдвигов я знаю.. а как реализовать их в с++?



ну... браток... эт" справку надо листать ;)
операция сдвига - >> и <<

2 sq_deep
:) спасибо что сказали про 3 и 4. а я сижу и ломаю голову, думаю раз человек спрашивает, значит как то можно... уже целый лист исписал

249
31 марта 2005 года
DissDoc
639 / / 01.10.2004
Цитата:
Originally posted by squirL
ну... браток... эт" справку надо листать ;)
операция сдвига - >> и <<

2 sq_deep
:) спасибо что сказали про 3 и 4. а я сижу и ломаю голову, думаю раз человек спрашивает, значит как то можно... уже целый лист исписал



Не, спасибо за ответ конечно! Но опять не т! Пример можно написать? Например
y = d/2;
Как это будет выглядеть с использованием сдвига?

2
31 марта 2005 года
squirL
5.6K / / 13.08.2003
Цитата:
Originally posted by DissDoc
Не, спасибо за ответ конечно! Но опять не т! Пример можно написать? Например
y = d/2;
Как это будет выглядеть с использованием сдвига?


а если бы я написал, что оператор деления - / вы бы тоже спросили пример???

очевидно:

 
Код:
include <iostream>

int main()
{
   int x=6;
   x=x>>1;
   std::cout<<"x = "<<x;
   /* результат x=2 */
}
425
31 марта 2005 года
sq_deep
498 / / 18.02.2005
Цитата:
Originally posted by squirL
а если бы я написал, что оператор деления - / вы бы тоже спросили пример???

очевидно:

 
Код:
include <iostream>

int main()
{
   int x=6;
   x=x>>1;
   std::cout<<"x = "<<x;
   /* результат x=2 */
}


Ну, squirL, эдак вы человека совсем запутаете. Он же про элементарный синтаксис спрашивает. Предлагаю следующее.

 
Код:
int main()
{
   int x=6;
   x = x >> 1;   // результат x=3
   x = x << 2;   // результат x=12
}
А в выражении std::cout<<"x = "<<x "<<" — переопределённая операция, ничего общего, кроме синтаксиса, со сдвигом не имеющая.
249
31 марта 2005 года
DissDoc
639 / / 01.10.2004
Цитата:
Originally posted by sq_deep
Ну, squirL, эдак вы человека совсем запутаете. Он же про элементарный синтаксис спрашивает. Предлагаю следующее.
 
Код:
int main()
{
   int x=6;
   x = x >> 1;   // результат x=3
   x = x << 2;   // результат x=12
}
А в выражении std::cout<<"x = "<<x "<<" — переопределённая операция, ничего общего, кроме синтаксиса, со сдвигом не имеющая.


А! Все работает! Понятно, спасибо

11K
31 марта 2005 года
DesignD
2 / / 31.03.2005
Цитата:
Originally posted by sq_deep
 
Код:
int x=6;
   x = x << 2;   // результат x=[color=red]12[/color]

x = x << 2 означает умножить x на 4, а не на 2.

Код на возведение в степень

Код:
int number = 7;  // число
  int power  = 5;  // степень
 
  int res = 0;
  int number2 = number;
  for(int j=1;j<power;j++)
  {
    int mask = 0x40000000;
    for(int i=30;i>=0;i--)
    {
      if(number&mask)
      {
        res=res + (number2<<i);
      }
      mask= mask>>1;
    }
    number2 = res;
    res = 0;
  }
  sprintf("%d в степени %d равна %d", number, power, number2);
2
31 марта 2005 года
squirL
5.6K / / 13.08.2003
Цитата:
Originally posted by DesignD
x = x << 2 означает умножить x на 4, а не на 2.



вы невнимательны, коллега :)

sq_deep написал:

 
Код:
int main()
{
   int x=6;
   x = x >> 1;   // результат x=3
   x = x << 2;   // результат x=12
}

результат выполнения программы будет действительно
х=12

2sq_deep
Цитата:

Ну, squirL, эдак вы человека совсем запутаете.


а мне можно, я не программер :)

11K
31 марта 2005 года
DesignD
2 / / 31.03.2005
Цитата:
Originally posted by squirL
вы невнимательны, коллега :)

Не-а. Уставший. :)

9.5K
31 марта 2005 года
nikiforov
24 / / 21.03.2005
Цитата:
Originally posted by DesignD
x = x << 2 означает умножить x на 4, а не на 2.

Код на возведение в степень
Код:
int number = 7;  // число
  int power  = 5;  // степень
 
  int res = 0;
  int number2 = number;
  for(int j=1;j<power;j++)
  {
    int mask = 0x40000000;
    for(int i=30;i>=0;i--)
    {
      if(number&mask)
      {
        res=res + (number2<<i);
      }
      mask= mask>>1;
    }
    number2 = res;
    res = 0;
  }
  sprintf("%d в степени %d равна %d", number, power, number2);



Насколько я понял, следующий фрагмент:

 
Код:
int mask = 0x40000000;
    for(int i=30;i>=0;i--)
    {
      if(number&mask)
      {
        res=res + (number2<<i);
      }
      mask= mask>>1;
    }

реализует операцию умножения "вручную". Зачем ? Если только для примера...

Возведение в степень можно выполнить оптимальнее. B сдвиги здесь косвенно задействованы. Идея в том, что степень представляется в виде разложения по степеням двойки:

n^10 = n^8 + n^2

Более оптимальный вариант (по сравнению с 9 умножениями) выглядит так:

a = n^2; // 1 умножение
r = (a^2)^2 + a; // 2 умножения, 1 сложение

К сожалению, не помню, как нызвается этот метод.
425
01 апреля 2005 года
sq_deep
498 / / 18.02.2005
Цитата:
Originally posted by nikiforov
n^10 = n^8 + n^2


Вы ошиблись:
n^10 = n^8 [SIZE=3][COLOR=red]*[/COLOR][/SIZE] n^2

И вообще, коллеги, искать алгоритмы возведения в степень или (тем более) алгоритмы извлечения корней с помощью сдвигов — задача неблагодарная. Двоичный сдвиг есть это по определению целочисленное умножение или деление на степень двойки. Вероятно, если приложить достаточные усилия, можно построить какие-то алгоритмы, которые будут активно использовать умножение на 2^k, но только это умножение не будет ключевой идеей таких алгоритмов. Даже при большом старании автор такого алгоритма не сможет гордо сказать "я возвожу в степень с помощью операции битового сдвига". То есть, сказать-то он, конечно, сможет, но только это не будет правдой.

Поэтому дискуссия эта кажется мне бесплодной.

2
01 апреля 2005 года
squirL
5.6K / / 13.08.2003
Цитата:
Originally posted by sq_deep
Вы ошиблись:
n^10 = n^8 [SIZE=3][COLOR=red]*[/COLOR][/SIZE] n^2

И вообще, коллеги, искать алгоритмы возведения в степень или (тем более) алгоритмы извлечения корней с помощью сдвигов — задача неблагодарная. Двоичный сдвиг есть это по определению целочисленное умножение или деление на степень двойки. Вероятно, если приложить достаточные усилия, можно построить какие-то алгоритмы, которые будут активно использовать умножение на 2^k, но только это умножение не будет ключевой идеей таких алгоритмов. Даже при большом старании автор такого алгоритма не сможет гордо сказать "я возвожу в степень с помощью операции битового сдвига". То есть, сказать-то он, конечно, сможет, но только это не будет правдой.

Поэтому дискуссия эта кажется мне бесплодной.



добавлю. изобретать подобные тяжеовесные алгоритмы лишено смысла еще по одной причине. всегда надо думать о рациональности. если мы реализуем на С умножение/деление на целую степень двойки путем битового сдвига, это нормально - поскольку x<<2^n или x>>2^n будет преобразовано в аналогичную машинную инструкцию. более того - если мы напишем просто x*2^n, то на ассемблерном уровне это будет та же машинная команда. реализовывать же подобный алгоритм возведения в степень, когда есть ассемблерная инструкция возведения в степень - это создание велосипеда с квадратными колесами. представьте, во что развернется ваша функция :o

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог