БлогNot. C++: степень двойки, ближайшая сверху к заданному числу

C++: степень двойки, ближайшая сверху к заданному числу

Вот, народу понадобилась функция для расчёта размера буферов, чтоб кратными степени 2 были... посмотрел - парятся, какие-то циклические возведения числа в степень и рекурсии выдумывают... меж тем, на побитовых операциях можно сделать простое и красивое решение:

#include <iostream.h>

long clp2(long x) { 
 //Ищет и возвращает ближайшую к x сверху степень двойки
 //Вообще говоря, предполагает, что число 32-разрядное
 x--;
 for (int p=1; p<32; p<<=1) x |= (x >> p);
 return ++x;
}

void main () {
 long x;
 cout << "x=";
 cin >> x;
 cout << clp2(x);
}

Можно, конечно, попытаться быть ещё круче, раз всё равно предполагаем 32-разрядный long, предположим и 64-разрядный double:

long clp2(long x) { 
 union { double f; long i[2]; } convert;
 convert.f = x;
 if ((convert.i[1] & 0xFFFFF) | convert.i[0]) return 1<<((convert.i[1]>>20) - 0x3FE);
 else return x;
}

Как видите, здесь вообще нет цикла, но есть union и один-единственный условный оператор.

Единственный "минус" - будет работать не во всех средах, так, в старом Borland C++ 3.1 не сработало, а вот в C++ Builder 6 - уже да. Также быстродействие будет зависеть от аппаратной реализации типа double.

Но и классическому "школьному" решению с вычислением степеней двойки нельзя отказать в достоинствах, тем более, что вычисление степеней в данном случае тоже можно оптимизировать операцией побитового сдвига:

long clp2(long x) {
 long p2=1;
 while (1) {
  if (p2>=x) return p2;
  p2<<=1;
 }
 return 0;
}

Если надо проверить, является ли натуральное число value степенью двойки, вот красивая функция. Она считает ноль степенью двойки, если это не так, добавьте дополнительное условие в тело is_power_of_two.

#include <iostream>
using namespace std;

int is_power_of_two (int value) {
 return !(value & (value - 1));
}

int main() {
 cout << endl << is_power_of_two(0); //0 и 1 - степень двойки
 cout << endl << is_power_of_two(1); 
 cout << endl << is_power_of_two(12);
 cout << endl << is_power_of_two(127);
 cout << endl << is_power_of_two(128);
 cin.sync(); cin.get(); return 0;
}

27.03.2012, 12:19 [18650 просмотров]


теги: числа c++ программирование алгоритм

К этой статье пока нет комментариев, Ваш будет первым