Jak przy pomocy przesuniecia bitowego w lewo wypisać liczbę binarnie?

0

Jak przy pomocy przesniecia bitowego w lewo wypisać liczbę binarnie? w c ++
no dobra ja zrobiłem coś takiego:

void function(int liczba)
{
    int liczba1 = liczba;

    if (liczba > 0) {
        liczba = liczba >> 1;
        function(liczba);
        cout << (liczba1 & 1);
    }
}
int main()
{

    function(4532);
}

ale chce w lewo

0

Ale nie samego przesunięcia – koniunkcja się jeszcze przyda, do wyłuskania najmłodszego bitu.


Edit: Edytowałeś post i teraz mój głupio wygląda. Zmienna pomocnicza nie jest Ci potrzebna – do parametru funkcji możesz bezpośrednio przekazać wynik przesunięcia.

Zobacz, tak wygląda wyświetlenie od najstarszego bitu do najmłodszego:

// 44 = 101100
void toBin(int number)
{
  if(number > 0)
  {
    toBin(number >> 1);
    cout << number & 1;
  }
}

A tak od najmłodszego do najstarszego:

// 44 = 001101
void toBin(int number)
{
  if(number > 0)
  {
    cout << number & 1;
    toBin(number >> 1);
  }
}

Różnica to wyświetlenie cyferki przed wywołaniem rekurencyjnym, zamiast po nim. Przy czym te kody nie wyświetlą niczego, jeśli w argumencie dostaną 0 – to pasuje sobie zabezpieczyć. ;)

A jak koniecznie musisz użyć przesunięcia w lewo to koniunkcję zawsze przeprowadzaj na najstarszym bicie, a nie na najmłodszym. Reszta pozostaje tak jak pokazałem wyżej – albo najpierw wywołanie rekurencyjne, albo wyświetlenie cyfry.

0

110 AND
100
1100 AND
_100
11000 AND
__100
ale skąd mam wiedzieć ile bitów ma liczba oraz ile kiedy to zakończyć, to trudne jest

0
bartek164 napisał(a):

ale skąd mam wiedzieć ile bitów ma liczba […]

Wiesz czym jest sizeof? No, to teraz wiesz ile bitów ma liczba. Jeśli problemem dla Ciebie jest pominięcie wiodących zer, to nic nie stoi na przeszkodzie, aby w pętli przesuwać liczbę w lewo dotąd, aż najstarszy bit będzie zapalony. Oczywiście pod warunkiem, że wejściowa liczba jest większa od 0.

[…] oraz ile kiedy to zakończyć […]

Skoro wiesz ile bitów ma zmienna liczbowa, to możesz określić liczbę iteracji pętli.


Niżej podaję swoją propozycję, ale nie wiem czy nie przekombinowałem – rzadko piszę w C(++):

void toBin(unsigned int number)
{
  if(number > 0)
  {
    unsigned int bits = sizeof(number) * 8;
    unsigned int mask = 1 << (bits - 1);
    unsigned int iter = bits;
    
    while((number & mask) == 0)
    {
      number <<= 1;
      --iter;
    }
    
    while(iter-- > 0)
    {
      std::cout << ((number & mask) >> (bits - 1));
      number <<= 1;
    }
  }
  else
    std::cout << 0;
}

Kod działa prawidłowo. Choć użyłem w nim unsigned int, bo mi się krzaczył z int – wszystko przez ciągłe modyfikowanie najstarszego bitu, czyli bitu znaku. ;)


Edit: Dla typu int też się da. Sama zmiana typu danych parametru i zmiennych lokalnych spowoduje, że 0 będą ładnie wyświetlane, ale zamiast 1 wyświetlać będzie -1. Czyli dla liczby 44 jako int, funkcja wypluje na konsoli -10-1-100. Tak więc przy wyświetlaniu cyferki, wynikowi koniunkcji i przesunięcia należy zmienić znak:

std::cout << -((number & mask) >> (bits - 1));

Tutaj jest działający przykład dla typu int.

1
bartek164 napisał(a):

ale jak dla architektury? bo u mnie siezof(3) daje mi 4 i razy 8 to jest 32

W skrócie, jeśli kompilator wypluwa 32-bitowy kod, to zmienne typu int zajmują 32 bity. unsigned int też tyle zajmuje, bo od zwykłego int odróżnia go brak wsparcia znaku (przechowuje tylko liczby naturalne). Jeśli spełniasz powyższy warunkek, sizeof(int) zwróci 4.

Druga sprawa to sizeof(3). Ta instrukcja zwraca 4, bo domyślnie literał liczbowy jest typu int. Takie rzeczy sprawdza się w dokumentacji, a nie na forum. Zobacz więc do dokumentacji.


I pamiętaj – sizeof zwraca objętość w bajtach zmiennej, a nie ilość zapalonych bitów w liczbie, którą zmienna przechowuje. Do określenia liczby faktycznie używanych bitów trzeba napisać własny kod, co w pokazałem w przykładzie w poście wyżej. Najpierw pętla while pomija zera wiodące, dotąd aż trafi na pierwszy zapalony bit – od tego miejsca zaczyna się ”konwersja” w drugiej pętli while. Aby funkcja wiedziała ile zer zostało pominiętych, używa do tego licznika iteracji (zmienna iter), dekrementowanego w obu pętlach.

0

no ja napisałem coś takiego, jest hujo..... ale nie wiem jak to zrobiłeś aby nie mieć tych zer z przodu, bo na czym to polega u ciebie, jak to zrobiłeś, bo u mnie robie to 32 razy, czyli tyle ile ma bitów liczba

#include <iostream>
using namespace std;

void binary(unsigned num, int i = 1, int j = 1)
{
    unsigned bit_amount = 8 * sizeof(num);
    if (j <= bit_amount) {
        if (j != bit_amount)
            binary(num, i << 1, ++j);
        cout << ((num & i) ? "1" : "0");
    }
    
}

int main()
{
    binary(4);
}
0
bartek164 napisał(a):

ale nie wiem jak to zrobiłeś aby nie mieć tych zer z przodu, bo na czym to polega u ciebie, jak to zrobiłeś, bo u mnie robie to 32 razy, czyli tyle ile ma bitów liczba

No tak to zrobiłem:

while((number & mask) == 0)
{
  number <<= 1;
  --iter;
}

Jeśli liczba jest większa niż 0 to przesuwam bity w lewo dotąd, aż najstarszy bit będzie zapalony. Jednocześnie zmniejszam licznik iteracji, aby w następnym kroku (pętli) wiedzieć ile razy wykonać wyświetlenie wartości najstarszego bitu.

Jeśli chcesz to zobić rekurencyjnie, to najpierw musisz zrobić to samo (czyli przesuwać liczbę w lewo aż zapali się najstarszy bit), zliczyć ile iteracji pozostało, a następnie wywołać funkcję rekurencyjną, która dokona wyświetlenia danych.

Czyli potrzebujesz dwóch funkcji. Pierwsza (nierekurencyjna) sprawdzi czy liczba jest równa 0 i jeśli tak, wyświetli w konsoli 0, a jeśli nie to usunie zera wiodące i wywoła drugą funkcję. Ta druga – rekurencyjna – będzie wyświetlać wartość najstarszego bitu i wywoływać samą siebie rekurencyjnie dotąd, aż licznik rekurencji dojdzie do 0.

Czyli można to zrobić tak:

using namespace std;

#define bits (sizeof(number) * 8)
#define mask (1 << (bits - 1))

void toBinRecursive(int number, int iter)
{
  if(iter > 0)
  {
    cout << -((number & mask) >> (bits - 1));
    toBinRecursive(number << 1, iter - 1);
  }
}

void toBin(int number)
{
  if(number > 0)
  {
    int iter = bits;
    
    while((number & mask) == 0)
    {
      number <<= 1;
      --iter;
    }
    
    toBinRecursive(number, iter);
  }
  else
    cout << 0;
}

Do przetestowania tutaj. Ze stałych elementów – bits i mask – zrobiłem makra, bo szkoda pamięci. ;)

0

omg, zrobiłem to, wygląda jak wygląda, dzięki za pomoc


#include <iostream>

using namespace std;

void setbinary(unsigned num, int i, int j, int bit_amount)
{
    if (j <= bit_amount) {
        if (j != bit_amount)
            setbinary(num, i << 1, ++j, bit_amount);
        cout << ((num & i) ? "1" : "0");
    }
}
void binary(unsigned num)
{
    unsigned allbit = 8 * sizeof(num);
    int bit_amount = 0;
    unsigned mask = mask << bit_amount - 1;
    while ((num & mask) == 0) {
        ++bit_amount;
        mask >>= 1;
    }
    setbinary(num, 1, 1, allbit - bit_amount);
}

int main()
{

    binary(22);
return 0;
}
0

ale żem turtaj gafę popełnił :
zamiast :

unsigned mask = 1;
mask <<= bit_amount-1;

napisałem

unsigned mask = mask << bit_amount-1;

czyli na to wygląda że unsigned to większe od 0 lol

0

Straszny misz-masz zrobiłeś w tym kodzie…

Masz za dużo tego kodu, przede wszystkim za dużo zmiennych i parametrów. Po to podałem Ci przyklady, abyś zrozumiał jak to działa i jak wykonać zadanie pisząc jak najmniej kodu. A Ty wziąłeś mój kod i dowaliłeś do niego zmiennych, parametrów, warunków i for, nie wiedzieć dlaczego i po co.

Najpierw postaraj się zrozumieć jak to działa, następnie zobacz jak wygląda mój kod, a na koniec spróbuj go skrócić (a nie wydłużyć). Czytelna wersja iteracyjna jest tutaj:

#define bits (sizeof(number) * 8)
#define mask (1 << (bits - 1))

void toBin(int number)
{
  if(number > 0)
  {
    int iter = bits;
    
    while((number & mask) == 0)
    {
      number <<= 1;
      --iter;
    }
    
    while(iter-- > 0)
    {
      cout << -((number & mask) >> (bits - 1));
      number <<= 1;
    }
  }
  else
    cout << 0;
}

Na niej bazuj, a rekurencji w tym przypadku nie używaj, bo nie ma ona sensu.

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