operacje bitowe

0

Witam, mam do napisania 3 funkcje, z którymi nie mogę sobie poradzić. Bardzo proszę o jakieś podpowiedzi. Wszystkie funkcje dotyczą 32 bitów

  1. Funkcja która zeruje co drugi bit. Podaję liczbę całkowitą, funkcja zeruje co drugi bit i wynik podaje też jako liczbę dziesiętną.
  2. Funkcja która wykrywa sekwencje 101 w liczbie binarnej. Podaję liczbę całkowitą program zlicza sekwencje i na wyjściu podaje ilość.
  3. Funkcja która w każdym bajcie wczytanej liczby całkowitej zamieni miejscami jej połówki. Podaję liczbę całkowitą i wynik również jest w postaci liczby dziesiętnej.
0

ale czego nie potrafisz?

0

W ogóle nie rozumiem jak działają te operacje bitowe, główny problem to z maskami, bo chyba będą tutaj potrzebne,a nie wiem jak ich użyć. Chciałbym jakąś podpowiedź, co trzeba zrobić w tych zadaniach.

0
#include <iostream>
#include <bitset>

int main()
{
    std::string binary = std::bitset<8>(128).to_string(); //to binary
    std::cout<<binary<<"\n";

    unsigned long decimal = std::bitset<8>(binary).to_ulong();
    std::cout<<decimal<<"\n";
    return 0;
}

tutaj bedziesz miec liczbe binarna w stringu, wystarczy ze teraz zrobisz zerowanie co drugi znak. znajdziesz sekwencje 101 (a co z sekwencja 10101? jak bedzie liczona?) a z bajtami to dzielisz od prawej(czyli od konca) na 8 znakow i robisz swapa. pozniej jak pokazane na przykladzie uzywasz bitsetu zeby odwrocic z powrotem liczbe

0

w przypadku 10101 będą 2 sekwencje.
Dziękuję za wskazówki ;)

0

http://eduinf.waw.pl/inf/alg/002_struct/0007.php

  1. W pętli lecisz od 0 do 31 i zerujesz co drugi bit. A zerowanie bitu polega na koniunkcji negacji, czyli jeśli masz 0010 to negacja to 1101 i koniunkcja z tym zeruje drugi bit od prawej.
  2. Sprawdzanie czy dany bit jest ustawiony to po prostu sprawdzanie czy koniunkcja daje liczbę różną od 0. Czyli koniunkcja z 0010 daje coś niezerowego -> drugi bit jest ustawiony.
  3. Pewnie da się sprytniej, ale można po prostu sprawdzić jakie bity są ustawione dla danego bajtu i po potem ustawić je po przestawieniu.
3
uint32_t v;
cin >> v;
v = v & 0xAAAAAAAA; // lub 0x555555555
cout << v;
uint32_t v;
cin >> v;
int count = 0;
for(int i = 0; i < 32 - 2; ++i)
{
	if(((v >> i) & 7) == 0x5) { // 0x5 = 101b
		++count;
	}
}
cout << count;
uint32_t v;
cin >> v;
for(int i = 0; i < 4; ++i)
{
	uint8_t temp = static_cast<uint8_t>((v >> (i * 8)) & 0xFF);
	temp = ((temp & 0xF) << 4) | (temp >> 4);
	v = (v & ~(0xFF << i * 8)) | (temp << i * 8);
}
cout << v;
0

Udało mi się zrobić zerowanie bitów, ale dalej nie rozumiem tej sekwencji. Co mi da sprawdzenie czy bit jest ustawiony?

0

Wszyystko co napisał mwl4 super działa, ale nie rozumiem 2 ostatnich kodów, szczególnie ostatniego :/

0

Śpieszę z wyjaśnieniem (aczkolwiek nie wiem czy będę potrafił to przetłumaczyć na język ludzi)

  1. Iterujemy od 0 do 29 włącznie. Dla każdego przebiegu pętli przesuwamy bity o tyle ile wynosi i, następnie wykonujemy operację and z argumentem 111b, a wynik porównujemy do 101b.
    Przykład:
v = 1010001010b

i = 0
przesuwamy bity v o 0 w prawo => t = 1010001010b
wykonujemy operację and z argumentem 111b:
  1010001010b
& 0000000111b
= 0000000010b
porównujemy wynik z 101b => 010b != 101b

i = 1
przesuwamy bity v o 1 w prawo => t = 0101000101b
wykonujemy operację and z argumentem 111b:
  0101000101b
& 0000000111b
= 0000000101b
porównujemy wynik z 101b => 101b == 101b => zwiększamy licznik o 1.

i = 2
  .... itd. aż i = 29
  1. Iterujemy od 0 do 3 włącznie. Dla każdego przebiegu pętli obliczamy wartość tymczasową (tj. bajt o numerze i-tym, a następnie połówki odwracamy). Potem scalamy wartość v ( w której zerujemy aktualny bajt ) z bajtem odwróconym przesuniętym w lewo o odpowiednią pozycję.
    Przykład:
v = 0xABCDEF01 = 10101011 11001101 11101111 00000001b

i = 0
przesuwamy bity v o (i * 8) = 0 w prawo => temp = 10101011 11001101 11101111 00000001b
wykonujemy operację and z argumentem 0xff (11111111b):
  10101011 11001101 11101111 00000001b
& 00000000 00000000 00000000 11111111b
= 00000000 00000000 00000000 00000001b
do temp wrzucamy wartość temp z przesuniętymi bitami w prawo o 4 oraz wartość temp z wykonaną operacją and z argumentem 0xF (1111b) i przesuniętymi bitami w lewo o 4, więc:
00000001b przesuwamy w prawo o 4 => 00000000b
00000001b & 1111b => 00000001b => przesuwamy w lewo o 4 => 00010000b
scalamy wyniki:
  00000000b
| 00010000b
= 00010000b
teraz do v wrzucamy wartość v z wyzerowanym aktualnym bajtem i wartością obliczoną wyżej:
~(0xFF << i * 8) = wychodzi maska dzięki której możemy wyzerować aktualny bajt (11111111b przesuwamy w lewo o i*8 a następnie wynik negujemy).
v = v & maska | temp przesunięty w lewo o i*8

i tak z każdym i aż do 3 włącznie.
0

Super, dziękuję, już jest to dla mnie trochę jaśniejsze ☺

1 użytkowników online, w tym zalogowanych: 0, gości: 1