2016-03-11 5 views
1

Я работаю над проектом, и мне нужно получить последние n битов двоичного кода. Я что-то пробовал, но я не очень хорошо работаю. Это код:Получить последние n бит двоичного кода

long long int to_bin(int n) 
{ 
    long long int Fin=0,pow=1; 
    while(n) 
    { 
     Fin=Fin+(n%2)*pow; 
     n/=2;pow*=10; 
    } 
return Fin; 
}   // returns binary 

int get_last_n_digits(int nr , int n_dig) 
{ 
    int l_digits =0 , power = 1; 
     for(int i = 0 ; i < n_dig ; i++) 
      power *=10; 
     l_digits = nr%power; 
    return l_digits; 
}   //returns last digits of a number 

А к примеру, мне нужны последние 2 бита двоичного представления 245, то есть что-то вроде этого:

get_last_n_digits(to_bin(254,S) ; 

и результат: 4; Что случилось?

+1

Читайте о побитовом И. – ZDF

+0

Да, вы правы, Извините –

ответ

2

Что вы делаете, это создание целочисленного значения, десятичное представление которого соответствует двоичному представлению входного значения. Я слышал о «двоичном кодированном десятичном разряде», поэтому я буду называть это «десятичной кодированной двоичной». Ха-ха!

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

Ваша to_bin функция уже сработала, поэтому я скопировал ее ниже как DecimalCodedBinary.

Чтобы отбросить цифры более высокого порядка и сохранить низкие цифры N для числа, представленного в базе B, вам просто нужно получить X (mod B^N) (где «^» - возведение в степень).

Итак, для работы с базой 10 я сделал специальную функцию, Pow10, которая возвращает 10 в силу аргумента.

И, наконец, LowDigitsDecimal является правильной реализацией get_last_n_digits, возвращая nr % Pow10(n_dig).

#include <iostream> 
#include <iomanip> 

unsigned long long DecimalCodedBinary(unsigned int n) { 
    unsigned long long pow10 = 1; 
    unsigned long long result = 0; 
    while(n) { 
     result += pow10 * (n % 2); 
     n /= 2; 
     pow10 *= 10; 
    } 
    return result; 
} 

unsigned long long Pow10(int exponent) { 
    if(exponent < 0) return 0; 
    unsigned long long pow10 = 10; 
    unsigned long long result = 1; 
    while(exponent) { 
     if(exponent % 2) result *= pow10; 
     exponent /= 2; 
     pow10 *= pow10; 
    } 
    return result; 
} 

unsigned long long LowDigitsDecimal(unsigned long long nr, int count) { 
    unsigned long long modulo = Pow10(count); 
    return nr % modulo; 
} 

int main() { 
    unsigned long long dcb_val = DecimalCodedBinary(254); 
    std::cout << dcb_val << "\n"; 
    unsigned long long dcb_val_low_2 = LowDigitsDecimal(dcb_val, 2); 
    std::cout << std::setw(8) << std::setfill('0') << dcb_val_low_2 << "\n"; 
5

Попробуйте

static inline long get_last_n_bits(long num, int nbbits) { 
    return num & ((1L<<nbbits)-1); 
} 

и читать больше о бинарных представлениях и операциях поразрядных; вы можете даже сделать тип num формального аргумента шаблона ... затем использовать get_last_n_bits<long> или get_last_n_bits<uint64_t> и т.д ..

затем проверить, что get_last_n_bits(245,2) равен 1.

Ваша терминология не так, цифра не бит или вы должны сказать несколько двоичного разряда

+1

Просто сказать, что у нас недавно была ошибка, потому что мы долго не использовали '1L << nbbits'. Может быть, безопаснее добавить классификатор для типа константы? – Plouff

2

Если я правильно понял ваш ответ правильно (и я не уверен, что я делаю, просьбу уточнить), вы можете использовать изменения для решения этой проблемы:

int get_last_n_digits(int nr , int n_dig) 
{ 
    int shift = (sizeof(nr) * 8) - n_dig; 
    return (nr << shift) >> shift; 
} 

Первая смена (левая) очищает все нежелательные биты, вторая возвращает желаемых.

2

Demo

Для чтения/выберите биты в определенных позициях вы должны скрывать, или маски, остальные биты. Одним из способов достижения этого является побитовый оператор AND: & (не логический и, &&).Если предположить, что речь идет о ряде 8 бит, если вход 15 и маска 7, результат 7:

Input: decimal 15 as binary: 0000 1111 & 
Mask: decimal 7 as binary: 0000 0111 
------------------------------------------ 
Output: decimal 7 as binary: 0000 0111 

Ваша проблема на самом деле, чтобы найти правильную маску. Если вас просят за последние 4 бита, ваша маска должна быть 0000 1111 (15 десятичных знаков, F гекса). Если вас просят за последние две цифры, ваша маска должна быть 0000 0011 (3 десятичных, 3 гекса). Шаги, чтобы найти маску для последних п битов:

  1. Установить все биты в 1. Это может быть сделано путем отрицая нуля: ~0 ->1111 1111 (255 десятичное, FF гекса)
  2. Сдвиг n бит влево : ~0 << n. Если n равно 2, вы получите 1111 1100
  3. Отклонить результат: ~(~0 << n). Если n равно 2, вы получите 0000 0011.

После того, как у вас есть маска, все, что вам нужно сделать, это использовать побитовое И:

output = input & ~(~0 << n) 

Это то, что вы получите в конце:

unsigned get_last_n_bits(unsigned u, int n) 
{ 
    return u & ~(~0U << n); 
} 

При отображении результат в двоичной базе невозможен с помощью стандартных ручных манипуляторов. Вы не можете написать что-то похожее на cout << hex << number: нет манипулятора bin. Тем не менее, он может быть отображен, если число преобразуется в bitset: cout << bitset<width>(number):

#include <iostream> 
#include <bitset> 
using namespace std; 

unsigned get_last_n_bits(unsigned u, int n) 
{ 
    return u & ~(~0U << n); 
} 

int main() 
{ 
    cout << bitset<8>(get_last_n_bits(254, 2)); // displays 00000010 
    return 0; 
}