[C++] Operatory/operacje bitowe.

Chungu
Użytkownik
Użytkownik
Posty: 121
Rejestracja: 21 paź 2016, o 20:57
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 42 razy

[C++] Operatory/operacje bitowe.

Post autor: Chungu »

Witam.
Napisałem taki program, który ma zapisać mi 2 daty (ograniczone warunkami, które podam za chwilę) w postaci jednej zmiennej:
-Lata tylko z XXI wieku-od 2000 do 2127 tak by można je reprezentować tylko liczbami [0,127]
-dalej normalnie-dla miesięcy 4 bity(można tak zapisać liczby [0,15])
-no i dni [0,31] a wiec 5 bitów
razem dla jednej daty:16 bitów ale, że mają być 2 to 32 bity.
Wiem, że int jest najczęściej 32 bitowy jednak już dla porządku dałem wszędzie int32_t (wiem może za duże, jak kilka osób mi sugerowało jednak na razie chce żeby wszystko działało)

no i potem przesuwam sobie te bity i chciałem sobie wyświetlić liczbę, której odpowiada układ bitów jaki uzyskałem (wyświetlam oczywiście w "main") - wyszło mi -25233793 wpisałem sobie to do kalkulatora żeby przeliczyło mi na system dwójkowy (o ten ... _liczb.php kalkulator). Wyszła mi liczba która ma +/- 64 bity no ale jak sobie biorę od prawej 32 to niby się zgadza... a te złe to chyba wszystkie 1...tylko:
1. skąd wzięły mi się te jedynki?
2.Czy to w ogóle ma prawo działać poprawnie?(proszę bardzo tylko o odpowiedź na to-na razie chce TYLKO żeby działało..."szczegółami" (takimi jak to, że typy parametrów są "za duże" mogę zająć się później))

Proszę o jakieś wskazówki jak taki problem rozwiązać... Przepraszam, że się aż tak rozpisałem ale chciałbym uzyskać dosyć precyzyjną odpowiedź/podpowiedź. A i dodam, że jestem POCZĄTKUJĄCY dlatego błąd może wynikać też z tego, że niezbyt dobrze mogłem poznać system dwójkowy czy sam temat operatorów bitowych.



Kod:

Kod: Zaznacz cały

#include <iostream>
#include <iomanip>

using namespace std;
int32_t pack(int32_t rr1, int32_t mm1, int32_t dd1, int32_t rr2, int32_t mm2, int32_t dd2);

int main()
{
    int32_t peroid=pack(2126,12,31,2127,12,30);
    cout<<peroid<<endl;
    return 0;
}
int32_t pack(int32_t rr1, int32_t mm1, int32_t dd1, int32_t rr2, int32_t mm2, int32_t dd2)
{
    int32_t zwracamy;
    rr1-=2000;
    rr2-=2000;
    dd1=dd1<<27;
    mm1=mm1<<23;
    rr1=rr1<<16;
    dd2=dd2<<11;
    mm2=mm2<<7;
    zwracamy=rr1|rr2|dd1|mm1|dd2|mm2|rr2;
    return zwracamy;
}


Z góry bardzo dziękuję za podpowiedzi oraz za cierpliwość do mojego ułomnego opisu!!!
kalwi
Użytkownik
Użytkownik
Posty: 1931
Rejestracja: 29 maja 2009, o 11:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 145 razy
Pomógł: 320 razy

[C++] Operatory/operacje bitowe.

Post autor: kalwi »

Wyświetl sobie tą liczbę w postaci binarnej zamiast się bawić w jakieś przeliczniki i sprawdź czy wyszło tak jak powinno. No i poza tym to nie zadziała, bo bez sensu masz tam parę rzeczy.

Kod: Zaznacz cały

#include <iostream>
#include <iomanip>
#include <bitset>

using namespace std;
int32_t pack(int32_t rr1, int32_t mm1, int32_t dd1, int32_t rr2, int32_t mm2, int32_t dd2);

int main()
{
    int32_t peroid = pack(2126,12,31,2127,12,30);
    cout << bitset<32>(peroid) << endl;
    return 0;
}

int32_t pack(int32_t rr1, int32_t mm1, int32_t dd1, int32_t rr2, int32_t mm2, int32_t dd2)
{    
    rr1 -= 2000; 			
    rr2 -= 2000; 			
    rr1 = rr1 << 25;		// 1111110
    mm1 = mm1 << 21;		// 1100
    dd1 = dd1 << 16;		// 11111
 	rr2 = rr2 << 9;			// 1111111
    mm2 = mm2 << 5;			// 1100
    						// 11110

    return rr1|mm1|dd1|rr2|mm2|dd2;
}
Chungu
Użytkownik
Użytkownik
Posty: 121
Rejestracja: 21 paź 2016, o 20:57
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 42 razy

[C++] Operatory/operacje bitowe.

Post autor: Chungu »

Dzięki ale kurcze, a mimo wszystko niby z tego przelicznika (może w nim tkwi błąd) wychodzi źle po czym finalnie mi wychodzą dobre liczby...
Napisałem trochę zapewne ułomny kod (który zamierzam oczywiście ulepszyć ale na razie chce, żeby w ogóle działał...) I sprawdziłem go dla kilku dat i kurcze... nie wiem jak, bo według Twoich (zapewne słusznych uwag) "mam kilka rzeczy bez sensu" z czego mniemam, że mój kod jest do bani.
Ponadto zastanawiam się dlaczego jak pogrubione unsigned zamienie na unsigned int32_t to nie działa(wiem, że w większości przypadków jest teraz int który ma 32 bity ale wole używać już wszędzie tego inte32_t a usnigned chce żeby przy przesuwaniu w prawo wchodziły mi zera)? Czyżby coś takiego nie istniało? (Wiem, wiem powinienem poszukać ale jakoś naprawdę nie mam już dzisiaj do tego siły a wujek Google nie wyrzucił bezpośrednich wyników). Dla potwierdzenia dołączam 3 linki ze screenami z działania programu i kompilatora (Code Blocks; na Dev C++ oczywiście coś nie działa-chodzi chyba o ten int32_t co chyba jest od standardu C++11 czy jak się to pisze):





[url]http://imageshack.com/a/img924/4386/VjQJXj.png[/url]

oto on:

Kod: Zaznacz cały

#include <iostream>
#include <iomanip>

using namespace std;
int32_t pack(int32_t rr1, int32_t mm1, int32_t dd1, int32_t rr2, int32_t mm2, int32_t dd2);
void showPeriod(int32_t peroid);

int main()
{
    int32_t peroid=pack(2006,9,5,2000,1,1);
    showPeriod(peroid);
    return 0;
}
int32_t pack(int32_t rr1, int32_t mm1, int32_t dd1, int32_t rr2, int32_t mm2, int32_t dd2)
{
    int32_t zwracamy;
    rr1-=2000;
    rr2-=2000;
    dd1=dd1<<27;
    mm1=mm1<<23;
    rr1=rr1<<16;
    dd2=dd2<<11;
    mm2=mm2<<7;
    zwracamy=rr1|rr2|dd1|mm1|dd2|mm2|rr2;
    return zwracamy;
}

void showPeriod(int32_t peroid)
{
    [b]unsigned[/b] r1,r2,m1,m2,d1,d2;
    d1=(unsigned int32_t)peroid>>27;
    m1=peroid<<5;
    m1=m1>>28;
    r1=peroid<<9;
    r1=r1>>25;
    d2=peroid<<16;
    d2=d2>>27;
    m2=peroid<<21;
    m2=m2>>28;
    r2=peroid<<25;
    r2=r2>>25;
    r2+=2000;
    r1+=2000;
    cout<<r1<<"/"<<m1<<"/"<<d1<<"-"<<r2<<"/"<<m2<<"/"<<d2<<endl;
}
-- 15 lis 2016, o 20:04 --

Kurcze te screeny trochę do bani, zaraz coś skombinuje... w każdym razie-to "coś" mi działa... niby tylko się cieszyć ale...
Ostatnio zmieniony 15 lis 2016, o 19:21 przez Chungu, łącznie zmieniany 1 raz.
kalwi
Użytkownik
Użytkownik
Posty: 1931
Rejestracja: 29 maja 2009, o 11:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 145 razy
Pomógł: 320 razy

[C++] Operatory/operacje bitowe.

Post autor: kalwi »

Hmm.. tak sobie myślę, że to mi się chyba coś jednak pomyliło i muszę zwrócić honor.

Ten fragment mnie zmylił:

Kod: Zaznacz cały

    zwracamy=rr1|rr2|dd1|mm1|dd2|mm2|rr2;
a konkretnie 2x rr2, dawno już na bitach nie operowałem
Ponadto zastanawiam się dlaczego jak pogrubione unsigned zamienie na unsigned int32_t to nie działa
Bo nie ma takiego typu jak

Kod: Zaznacz cały

unsigned int32_t
Jest uint32_t

I tak, w cpp int32_t jest dopiero od C++11. A nad screenshotami to popracuj trochę ;p
Chungu
Użytkownik
Użytkownik
Posty: 121
Rejestracja: 21 paź 2016, o 20:57
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 42 razy

[C++] Operatory/operacje bitowe.

Post autor: Chungu »

Haha, no tak definitywnie muszę popracować nad screenami. Czyli ogólnie jest ok? Czy jakoś mógłbym to "lepiej napisać"?-- 15 lis 2016, o 20:21 --A te nazwy zmiennych to wiem, że są do niczego... już mi kolega mówił. Muszę je zmienić.
kalwi
Użytkownik
Użytkownik
Posty: 1931
Rejestracja: 29 maja 2009, o 11:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 145 razy
Pomógł: 320 razy

[C++] Operatory/operacje bitowe.

Post autor: kalwi »

Tak teraz sobie skompilowałem ten Twój kod, to on nie działa poprawnie:

Kod: Zaznacz cały

#include <iostream>
#include <iomanip>

using namespace std;
int32_t pack(int32_t rr1, int32_t mm1, int32_t dd1, int32_t rr2, int32_t mm2, int32_t dd2);
void showPeriod(int32_t peroid);

int main()
{
    int32_t peroid=pack(2006,9,5,2000,1,1);
    showPeriod(peroid);
    return 0;
}
int32_t pack(int32_t rr1, int32_t mm1, int32_t dd1, int32_t rr2, int32_t mm2, int32_t dd2)
{
    int32_t zwracamy;
    rr1-=2000;
    rr2-=2000;
    dd1=dd1<<27;
    mm1=mm1<<23;
    rr1=rr1<<16;
    dd2=dd2<<11;
    mm2=mm2<<7;
    zwracamy=rr1|rr2|dd1|mm1|dd2|mm2|rr2;
    return zwracamy;
}

void showPeriod(int32_t peroid)
{
    int32_t r1,r2,m1,m2,d1,d2;
    d1=( uint32_t)peroid>>27;
    m1=peroid<<5;
    m1=m1>>28;
    r1=peroid<<9;
    r1=r1>>25;
    d2=peroid<<16;
    d2=d2>>27;
    m2=peroid<<21;
    m2=m2>>28;
    r2=peroid<<25;
    r2=r2>>25;
    r2+=2000;
    r1+=2000;
    cout<<r1<<"/"<<m1<<"/"<<d1<<"-"<<r2<<"/"<<m2<<"/"<<d2<<endl;
}

Kod: Zaznacz cały

2006/-7/5-2000/1/1
-- 15 lis 2016, o 21:37 --No i jeśli miałbym robić, to jakoś tak:

Kod: Zaznacz cały

typedef enum Bit_size {YEAR = 7, MONTH = 4, DAY = 5} Bit_size_t;
const unsigned int TYPE_SIZE = sizeof(int32_t) * 8 - 1;

int32_t pack(int32_t year_1, int32_t month_1, int32_t day_1, int32_t year_2, int32_t month_2, int32_t day_2)
{    
    year_1 -= 2000;          
    year_2 -= 2000;          
    unsigned int width = TYPE_SIZE - DAY;
    day_1 = day_1 << width; 
    width -= MONTH;    
    month_1 = month_1 << width;    
	width -= YEAR;    
	year_1 = year_1 << width;  
	width -= DAY;
    day_2 = day_2 << width; 
    width -= MONTH;    
    month_2 = month_2 << width;    
    return year_1 | month_1 | day_1 | year_2 | month_2 | day_2;
}
nie ma wtedy magic numbers
Chungu
Użytkownik
Użytkownik
Posty: 121
Rejestracja: 21 paź 2016, o 20:57
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 42 razy

[C++] Operatory/operacje bitowe.

Post autor: Chungu »

Ale skompilowałeś to co dałeś pierwsze w tym prostokącie "kod" tak?

Bo jeżeli tak to jak na mój gust to robi trochę różnicę (ja wpisałem Twoje daty sobie w moje i daje wynik ok) w 31 linijce: (Podkreślę jeszcze, że programuje od +/- miesiąca więc mogę gadać głupoty)

tam w operatorze rzutowania (którego de facto chyba nie powinienem używać bo to pozostałość po C chyba w Cpp są inne metody ale jeszcze o tym nie czytałem a czystego C trochę się też uczyłem
ale do rzeczy-zrobiłem tam rzutowanie, żeby przy przesuwaniu w prawo, które tam robię "wchodziły" mi zera a nie "niewiadome liczby"{no bo ta zmienna przekazywana do funkcji jest domyślnie ze znakiem} zmieniając tam z "mojego" unsigned int32_t na uint32_t korzystasz chyba ( z tego co czytałem-nie znałem tego przed tym jak mi o tym powiedziałeś ) z czegoś co jest znowu z czystego "c" i jest zadeklarowane w standardowej bibliotece stdint.h...co chyba nie jest kłopotem jeżeli dasz dyrektywę #include <stdint.h> bo z tego co mi wiadomo, a wiadomo mi w sumie mało, C jest podzbiorem C++ (mnie w Code Blocks działa dla Twojej daty)

Ale tak ogólnie to teraz patrze i ten mój kod jest trochę pokręcony-a wiadomo, chodzi żeby był jak najprostszy... zatem chyba muszę jeszcze wymyślić coś lepszego, prawdopodobnie w oparciu o Twoją propozycję- zatem dzięki!! A no i jeżeli gadam głupoty to proszę popraw mnie... Mam nadzieję, że coś rozumiesz z mojego toku rozumowania...



-- 15 lis 2016, o 23:42 --

Dorzucam screena z Code Blocks -- 15 lis 2016, o 23:54 --Kurcze, przepraszam mnie się pomieszało, teraz widzę, że faktycznie nie trzeba dawać dyrektywy... działa mi też bez... ;/ z tym uint32_t co jest od c++11
kalwi
Użytkownik
Użytkownik
Posty: 1931
Rejestracja: 29 maja 2009, o 11:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 145 razy
Pomógł: 320 razy

[C++] Operatory/operacje bitowe.

Post autor: kalwi »

Skompilowałem kod co wkleiłem w poprzednim poście.
Operator rzutowania to nie jest pozostałość po C, można go jak najbardziej używać (znaczy no w pewnym sensie jest, ale to tak jakby powiedzieć, że int też)
uint32_t jest od c++11, czyli od prawie 6 lat już obecny.
ANSI C jest podzbiorem C++98 i nowszych, C99 już nie.

Co do screenshotów - zainstaluj sobie program lighshot
Chungu
Użytkownik
Użytkownik
Posty: 121
Rejestracja: 21 paź 2016, o 20:57
Płeć: Mężczyzna
Lokalizacja: Łódź
Podziękował: 42 razy

[C++] Operatory/operacje bitowe.

Post autor: Chungu »

Tak wiem, wiem zreflektowałem się. Co do samego programu to dzięki za pomoc. Spróbuję w wolnej chwili ogarnąć Twoją propozycję. No tak, z pewnością skorzystam na przyszłość z tego programu.
ODPOWIEDZ