Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[SOLVED]C++ konwersje, przesuwanie bitow
View unanswered posts
View posts from last 24 hours
View posts from last 7 days

 
Reply to topic    Gentoo Forums Forum Index Polskie forum (Polish) Polish OTW
View previous topic :: View next topic  
Author Message
cinek810
Tux's lil' helper
Tux's lil' helper


Joined: 07 Jul 2007
Posts: 115

PostPosted: Wed Apr 16, 2008 6:43 pm    Post subject: [SOLVED]C++ konwersje, przesuwanie bitow Reply with quote

Witam, po pobraniu danych zapisuje je w taki sposob:
Code:

char pom1;
char pom2;
cin.get(pom1);
cin.get(pom2);
double pom_d=short(pom1)+(short(pom2)<<8);
REAL(data,i)=pom_d;


na koniec( obecnie nie wykonuje zadnych operacji)
chce te dane znowu wypisac takie jakimi je otrzymalem
probuje tak:
Code:

cout.put(char(( (int(REAL(data,i)/sqrt(iled)) & 0xff))));
cout.put(char(( (int(REAL(data,i)/sqrt(iled)) & 0xff00)) >> 8)); //TU JEST BLAD?


Jednak wypisywanie pom2 nie zawsze sie udaje..
Jeśli ktoś wpadnie na jakiś pomysł ze wskazaniem błędu będę wdzięczny.


Edited by Poe
ort


Last edited by cinek810 on Fri Apr 25, 2008 5:57 pm; edited 2 times in total
Back to top
View user's profile Send private message
dziadu
Guru
Guru


Joined: 04 May 2006
Posts: 467
Location: Kraków/Darmstadt/Munich

PostPosted: Thu Apr 17, 2008 11:51 am    Post subject: Reply with quote

Jakie dane? Jaki program? Podaj więcej szczegółów, pokaż listingi. Wtedy będę mógł sobie przekompilować i popróbować. Bo na razie tylko oglądam.
Back to top
View user's profile Send private message
cinek810
Tux's lil' helper
Tux's lil' helper


Joined: 07 Jul 2007
Posts: 115

PostPosted: Fri Apr 18, 2008 5:03 pm    Post subject: Reply with quote

heh.. program jest długi, a fragment tutaj dotyczy pobierania plików wav

w zasadzie cały kod masz tutaj... (ten w ktorym mysle, ze jest problem)
jesli jest gdzie indziej, coz.. trudno

pierwszy cytat kodu pobiera jakies dane w postaci char-ow, a drugi ma je wypisac.
Chodzi o to, żeby wyszło to samo.. takie same chary w takiej samej kolejności.
Back to top
View user's profile Send private message
13Homer
Guru
Guru


Joined: 12 Jul 2005
Posts: 461

PostPosted: Fri Apr 18, 2008 5:18 pm    Post subject: Reply with quote

Jaki to jest błąd?
_________________
Lenovo ThinkPad R61 / C2D@2.6.24 / nVidia Quatro NVS 140M / 2 GB RAM
Back to top
View user's profile Send private message
cinek810
Tux's lil' helper
Tux's lil' helper


Joined: 07 Jul 2007
Posts: 115

PostPosted: Fri Apr 18, 2008 7:20 pm    Post subject: Reply with quote

ok, kod programu:

Code:

#include<iostream>

using namespace std;

int main()
{
   for(int i=0;i<10;i++)
   {
      char pom1=char((double)rand()/RAND_MAX*255);
      char pom2=char((double)rand()/RAND_MAX*255);
      cout<<pom1<<pom2<<endl;
      double pomd=short(pom1)+(short(pom2)<<8);
      cout.put(char(((int(pomd)) & 0xff)));  //tutaj wychodzi mi zawsze pom1, jest OK
      cout.put(char(((int(pomd) & 0xff00) >> 8))); //BLAD chce zeby wyszlo pom2
      cout<<endl;
   }
   return 0;
}


Problem jest z drugim znakiem- nie zawsze zostaje on dobrze odtworzony, roznica jest- tak mi się wydaje- zawsze o jeden znak w tablicy ASCII
Back to top
View user's profile Send private message
13Homer
Guru
Guru


Joined: 12 Jul 2005
Posts: 461

PostPosted: Fri Apr 18, 2008 7:46 pm    Post subject: Reply with quote

Konstrukcja "double pomd=short(pom1)+(short(pom2)<<8);" jest do kitu, musi być coś w rodzaju
"double pomd=(short(pom1) & 0xFF)+((short(pom2) & 0xFF) <<8);". A to dlatego, że jeśli char ma kod > 127, to po zrzutowaniu na liczbę ze znakiem (w tym wypadku short) będzie to liczba ujemna (tak naprawdę char też jest ujemny w tym wypadku) i zostanie z przodu dopełniona jedynkami (w rozwinięciu binarnym oczywiście, a nie dziesiątkowym).
Możesz też skorzystać z "wersji" unsigned wszystkich zmiennych, ale nie testowałem tego.
Swoją drogą jakieś dziwne testy przeprowadzałeś, bo u mnie błędne były obydwie liczby, np.:
Code:
65494   100
41   65435
214   99

65479   65483
56   52
199   202

65512   50
23   65485
232   49

85   65475
65450   60
85   195

70   65421
65465   114
70   141

121   65440
65414   95
121   160

93   65410
65442   125
93   130

65522   65513
13   22
242   232

65442   65462
93   73
162   181

36   65434
65499   101
36   154

Zaś mój kod testowy wyglądał tak:
Code:
#include<iostream>

using namespace std;

int main()
{
for(int i=0;i<10;i++)
{
    char pom1=char((double)rand()/RAND_MAX*255);
    char pom2=char((double)rand()/RAND_MAX*255);
    cout<<(unsigned short)pom1<<"\t"<<(unsigned short)pom2<<endl;
    cout<<(unsigned short)~pom1<<"\t"<<(unsigned short)~pom2<<endl;
    int pomd=short(pom1)+(short(pom2)<<8);
//    cout<<(unsigned int)pomd<<endl;
    cout<<((unsigned short)((int(pomd)) & 0xff));  //tutaj wychodzi mi zawsze pom1, jest OK
    cout<<"\t"<<((unsigned short)(((int(pomd) & 0xff00) >> 8))); //BLAD chce zeby wyszlo pom2
    cout<<endl;
    cout<<endl;
   }
    return 0;
}

_________________
Lenovo ThinkPad R61 / C2D@2.6.24 / nVidia Quatro NVS 140M / 2 GB RAM
Back to top
View user's profile Send private message
dziadu
Guru
Guru


Joined: 04 May 2006
Posts: 467
Location: Kraków/Darmstadt/Munich

PostPosted: Fri Apr 18, 2008 9:07 pm    Post subject: Reply with quote

Code:
#include<iostream>

using namespace std;

int main()
{
   for(int i=0;i<10;i++)
   {
      unsigned char pom1=(unsigned char)((double)rand()/RAND_MAX*255);
      unsigned char pom2=(unsigned char)((double)rand()/RAND_MAX*255);
      cout<<pom1<<pom2<<endl;
      double pomd=short(pom1)+(short(pom2)<<8);
      cout.put(char(((int(pomd)) & 0xff)));  //tutaj wychodzi mi zawsze pom1, jest OK
      cout.put(char(((int(pomd) & 0xff00) >> 8))); //BLAD chce zeby wyszlo pom2
      cout<<endl;
   }
   return 0;
}


Pozdrawiam,
dziadu
Back to top
View user's profile Send private message
dziadu
Guru
Guru


Joined: 04 May 2006
Posts: 467
Location: Kraków/Darmstadt/Munich

PostPosted: Sat Apr 19, 2008 1:15 pm    Post subject: Reply with quote

Jeśli nie wiesz w czym problem, wykonaj ten program:
Code:
#include<iostream>
#include<cstdio>

#define PRINT(val) printf(#val " = \t0x%x\n", val)

using namespace std;

int main() {
   for(int i=0;i<10;i++) {
      unsigned char pom1=char((double)rand()/RAND_MAX*255);
      unsigned char pom2=char((double)rand()/RAND_MAX*255);
      PRINT(pom1);      PRINT(pom2);
      PRINT((short)pom1);   PRINT((short)pom2);
      double pomd=short(pom1)+(short(pom2)<<8);
      PRINT(short(pom1));   PRINT(short(pom2)<<8);
      PRINT(short(pom1)+(short(pom2)<<8));
      PRINT((int)pomd);
      cout << pom1 << pom2 << endl;
      cout.put(char(((int(pomd)) & 0xff)));  //tutaj wychodzi mi zawsze pom1, jest OK
      cout.put(char(((int(pomd) & 0xff00) >> 8))); //BLAD chce zeby wyszlo pom2
      cout<<endl;
      cout << "######################\n";
   }
   return 0;
}


i się zastanów. Jeśli nada będziesz miał wątpliwości to napisz, postaram się wyjaśnić.


Tak dla ciekawostki podam inne rozwiązanie problemu zaproponowane przez Jurka Grębosza. Może w tym przypadku jest to przerost formy nad treścią, ale może kiedyś w przyszłości się przydać. Ja szczerze mówiąc zawsze zapominam o tym, jak unie mogą być przydatne:
Code:
#include<iostream>
#include<cstdio>

using namespace std;

int main() {
   for(int i=0;i<10;i++) {

      struct pola {
         int pom1 : 8;
         int pom2 : 8;
      };

      union {
         pola a;
         unsigned int raw;
      };

      a.pom1 = char((double)rand()/RAND_MAX*255);
      a.pom2 = char((double)rand()/RAND_MAX*255);
      cout << (char)a.pom1 << (char)a.pom2 << endl;
      cout   << "Rozklad bitow= 0x"<< hex << raw
         << ", a.pom1= " << dec << a.pom1
         << ", a.pom2= " << dec << a.pom2
         << endl;
      double pomd = raw;

      cout.put(char(((int(pomd)) & 0xff)));  //tutaj wychodzi mi zawsze pom1, jest OK
      cout.put(char(((int(pomd) & 0xff00) >> 8))); //BLAD chce zeby wyszlo pom2
      cout << endl;

      cout << "######################\n";
   }
   return 0;
}

Back to top
View user's profile Send private message
cinek810
Tux's lil' helper
Tux's lil' helper


Joined: 07 Jul 2007
Posts: 115

PostPosted: Thu Apr 24, 2008 6:18 pm    Post subject: Reply with quote

OK. Wiem już gdzie jest błąd, ale mam pytanie w związku z wyjaśnieniem jakie podał 13Homer. Mianowicie- kiedy po zrzutowaniu na typ o większym rozmiarze pierwsze bity dopełniane są zerami a kiedy jedynkami?
Back to top
View user's profile Send private message
13Homer
Guru
Guru


Joined: 12 Jul 2005
Posts: 461

PostPosted: Thu Apr 24, 2008 9:00 pm    Post subject: Reply with quote

Jedynkami wtedy, gdy liczba jest ujemna, czyli najstarszy bit == 1, zerami wpp. Nie zmienia to wartości liczby jako takiej (czyli w notacji dziesiętnej), ale drastycznie zmienia reprezentację binarną, więc operacje na bitach są ryzykowne.
_________________
Lenovo ThinkPad R61 / C2D@2.6.24 / nVidia Quatro NVS 140M / 2 GB RAM
Back to top
View user's profile Send private message
cinek810
Tux's lil' helper
Tux's lil' helper


Joined: 07 Jul 2007
Posts: 115

PostPosted: Thu Apr 24, 2008 9:04 pm    Post subject: Reply with quote

hym.. jak to nie zmienia wartości liczby jako takiej?

Przecież, jeśli coś jedno bajtowego dopełni się jedynkami przez kolejny bajt- to wartość liczby ulegnie drastycznej zmianie.

nigdy za dobrze tego nie rozumiałem, więc proszę o wyrozumiałość.
Back to top
View user's profile Send private message
dziadu
Guru
Guru


Joined: 04 May 2006
Posts: 467
Location: Kraków/Darmstadt/Munich

PostPosted: Fri Apr 25, 2008 8:16 am    Post subject: Reply with quote

Oczywiscie, jest to inna reprezentacja jeśli chcesz liczbe ujemna dekodowac do systemu dziesietnego jako liczbe bez znaku. Ale kiedy pamietasz ze jest to liczba ujemna, to algorytm zamiany jest prosty: robisz inwersje bitową, a potem dodajesz 1, i tak np: oxfd to 11111101 -> inwersja -> 00000010 -> dodaj 1 -> 00000011 => 3, i w rzeczywistości 0xfd to jest -3.

Można też patrzeć ianczej:
Code:

+3 - 0x03 - 00000011
+2 - 0x02 - 00000010
+1 - 0x01 - 00000001
+0 - 0x00 - 00000000
-1 - 0xff - 11111111
-2 - 0xfe - 11111110
-3 - 0xfd - 11111101


Czyli to tak jakby normalne odejmowanie i zapożyczamy sobie jedynke gdzies tam na pozycji MSB+1.
Dlatego jak zwiekszasz rozmiar liczby to musisz dopisac nieznaczace jedynki na poczatku (przez analogie kiedy rozszerzasz liczbe dodatnia to dopisujesz nieznaczace zera na poczatku).

W twoim programie byl blad tego typu, ze jesli pierwsza liczba (8-bitowa) wygenerowana byla ujemna, to jej reprezentacja po konwersji na short miala 32-bity (ew. 16 ale to nic nie zmienia), zatem: 0xffffff__. Potem brales druga liczbe, niewazne juz czy ujemna czy dodatnia, robiles przesuneecie bitowe o 8 bitow i otrzymywales nowa liczbe: 0x1111??00. Nastepnie te dwie liczby dodawales:
Code:

  0x  f  f  f  f    f f      _  _
+ 0x  f  f  f  f    ? ?      0  0
---------------------------------
  0x  f  f  f  f  [(? ?)-1]  _  _


A ?-1 na 3 pozycjo otrzymywales bo mailes dzialnie typu: -1 + x = x-1
Jesli przypatrzysz sie swojemu programowi to zauwazysz, ze wlasnie jesli pierwsza liczba byla ujemna to druga po tej calej konwersji wychodzila wlasnie o jeden mniejsza.

..:: edit:
mała korekta w dodawaniu, oczywiście 1 odejmujemy od dwucyfrowej liczby a nie tylko od najmłodszej - choć bład pojawi się tylko w specyficznym przypadku kiedy będziemy mieć 0 jako młodszy bit, chyba, że sprytnie pożyczymy sobie jedynke z pozycji MSB, wtedy będzie wszystko okej

..:: edit:
dzieki cinek za wskazanie błedu - z rozpędu przepisalem HEX-y zamiast BIN-ów


Last edited by dziadu on Fri Apr 25, 2008 7:26 pm; edited 3 times in total
Back to top
View user's profile Send private message
13Homer
Guru
Guru


Joined: 12 Jul 2005
Posts: 461

PostPosted: Fri Apr 25, 2008 9:59 am    Post subject: Reply with quote

Jeśli liczbę -128 zapiszesz na 8 bitach, to dostaniesz 80, żeśli teraz zapiszesz ją na 16 bitach, to będzie to ff80, a jeśli na 32, to ffffff80 itd, czyli oznacza to tylko dopisanie jedynek na "nowych" miejscach. A negowanie znaku liczby, co doskonale opisał dziadu, to osobna sprawa.
_________________
Lenovo ThinkPad R61 / C2D@2.6.24 / nVidia Quatro NVS 140M / 2 GB RAM
Back to top
View user's profile Send private message
dziadu
Guru
Guru


Joined: 04 May 2006
Posts: 467
Location: Kraków/Darmstadt/Munich

PostPosted: Fri Apr 25, 2008 11:06 am    Post subject: Reply with quote

@13Homer, Mała korekta, 0x80 to będzie -127, na ośmiu bitach ze znakiem zapiszesz zakres -127,+127. Myśle, że to twoje przeoczenie ale pisze to, żeby cinek nie został wprowadzony w błąd.
Back to top
View user's profile Send private message
cinek810
Tux's lil' helper
Tux's lil' helper


Joined: 07 Jul 2007
Posts: 115

PostPosted: Fri Apr 25, 2008 5:57 pm    Post subject: Reply with quote

Popełniony błąd zrozumiałem i serdecznie dziękuje.

dziadu: nie rozumiem tego fragmentu:
dziadu wrote:

+3 - 0x03 - 00000011
+2 - 0x02 - 00000010
+1 - 0x01 - 00000001
+0 - 0x00 - 00000000
-1 - 0xff - ffffffff
-2 - 0xfe - fffffffe
-3 - 0xfd - fffffffd


Czy to miałbyć zapis dwujkowy? Czy w zamyśle było jakieś inne rozumowanie- a może po prostu troche mniej f-ów, dla zgodności rozmiaru...
[Edit]
pewnie tak..
Back to top
View user's profile Send private message
13Homer
Guru
Guru


Joined: 12 Jul 2005
Posts: 461

PostPosted: Fri Apr 25, 2008 6:48 pm    Post subject: Reply with quote

dziadu wrote:
@13Homer, Mała korekta, 0x80 to będzie -127, na ośmiu bitach ze znakiem zapiszesz zakres -127,+127. Myśle, że to twoje przeoczenie ale pisze to, żeby cinek nie został wprowadzony w błąd.

Wykonaj to:
Code:
int main() {
printf("%x %x\n",(unsigned char)-128, (unsigned short)-128);
}

Inaczej: 127 (dodatnie) + 127 (ujemne) + 1 (zero) == 255, a wszystkich liczb jest 256. Której brakuje?

EDIT :: Albo tak: jeśli jedynka na początku, to liczba ujemna, pozostałe bity dowolne, jest ich 2^7 = 128, jeśli na początku zero, to podobnie, ale same zera to zero, więc dodatnich jest 127. 128 + 127 + 1 = 256.
_________________
Lenovo ThinkPad R61 / C2D@2.6.24 / nVidia Quatro NVS 140M / 2 GB RAM
Back to top
View user's profile Send private message
dziadu
Guru
Guru


Joined: 04 May 2006
Posts: 467
Location: Kraków/Darmstadt/Munich

PostPosted: Fri Apr 25, 2008 7:24 pm    Post subject: Reply with quote

aj, racja, rozpedzilem sie, juz poprawiam posta wyzej


cinek810 wrote:
Popełniony błąd zrozumiałem i serdecznie dziękuje.

dziadu: nie rozumiem tego fragmentu:
dziadu wrote:

+3 - 0x03 - 00000011
+2 - 0x02 - 00000010
+1 - 0x01 - 00000001
+0 - 0x00 - 00000000
-1 - 0xff - ffffffff
-2 - 0xfe - fffffffe
-3 - 0xfd - fffffffd


Czy to miałbyć zapis dwujkowy? Czy w zamyśle było jakieś inne rozumowanie- a może po prostu troche mniej f-ów, dla zgodności rozmiaru...
[Edit]

pewnie tak..

@13Homer - zwracam honor :-]
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Polskie forum (Polish) Polish OTW All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum