Elektroda.pl
Elektroda.pl
X
CControls
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

C18 jak zrobiś przesuniecie bitowe liczby ujemnej

wilk125 21 Paź 2011 15:53 3113 13
  • #1 21 Paź 2011 15:53
    wilk125
    Poziom 23  

    Witam
    Kompilator C18.
    Mam liczbę int, która jest ujemna i chce ją przesunać o 4 miejsca w lewo:

    Code:
    int a=-34;
    
    long b;
    b=(long)a>>4;


    Przeczytałem gdzies że jak liczba jest ze znakiem to dopełnienie jest takie jak bit mówiacy o tym czy liczba jest dodatnia (0) lub ujemna (1) lub tylko zerami w zależnosci od kompilatora. Kompilator do PC-ta dopełnia taką wartością jaki jest znak, a C18 zawsze niestety zerami.


    Samo przesuniecie jest ok, tylko, że 4 starsze bity zostały dopełnione zerami, a chciałbym żeby były jedynkami, jak to zrobić?

    pozdrawiam
    tomek

    0 13
  • CControls
  • #2 21 Paź 2011 16:39
    dondu
    Moderator Mikrokontrolery Projektowanie

    Niestety C to nie assembler. Sam musisz zadbać o dodanie odpowiednich bitów.
    Nie sądzę, żeby w kompilatorze C18 było jakieś odstępstwo od tej reguły, ale mogę się mylić.

    0
  • Pomocny post
    #3 21 Paź 2011 16:39
    megao
    Poziom 23  

    wilk125 napisał:
    Samo przesuniecie jest ok, tylko, że 4 starsze bity zostały dopełnione zerami, a chciałbym żeby były jedynkami, jak to zrobić?


    Nie da się zrobić (po przesunięciu) sumy logicznej z czterema jedynkami na najstarszych pozycjach?

    0
  • Pomocny post
    #4 22 Paź 2011 18:00
    94075
    Użytkownik usunął konto  
  • CControls
  • #5 24 Paź 2011 08:13
    wilk125
    Poziom 23  

    megao napisał:

    Nie da się zrobić (po przesunięciu) sumy logicznej z czterema jedynkami na najstarszych pozycjach?

    Można tak zrobić i chyba tak zrobię tylko wcześniej muszę sprawdzić czy liczba była ujemna.


    albertb napisał:

    Autora nie chciałbym spotkać na drodze (pisze lewo, przesuwa w prawo ;-) )
    Albert


    faktycznie, miało być w prawo

    albertb napisał:

    A że się tak zapytam czy przypadkiem nie chodzi o dzielenie przez 2^n?
    Jeśli tak, to czemu po prostu nie dzielisz przez 2 do odpowiedniej potęgi?
    Albert


    Algorytm którego używam przesuwa bity, ale równie dobrze można dzielić tak jak piszesz, tylko jak używam dzielenia to program "rośnie" wiec chyba pozostanę przy sprawdzaniu najstarszego bitu i OR.

    pozdrawiam
    tomek

    0
  • #6 24 Paź 2011 18:26
    94075
    Użytkownik usunął konto  
  • #7 24 Paź 2011 23:29
    dioda1000
    Poziom 27  

    Witam
    Zaciekawił mnie ten temat .Też ciekaw jestem jak inne kompilatory to rozwiążą.
    int a=-34;
    long b;
    b=(long)a>>4;

    Kod: asm
    Zaloguj się, aby zobaczyć kod


    poz. dioda

    0
  • #8 25 Paź 2011 10:39
    94075
    Użytkownik usunął konto  
  • #9 01 Gru 2011 19:33
    labo
    Poziom 13  

    Odkopię temat, bo na stare lata uczę się C aby pomóc przy sprawdzianie. :)

    Panowie, jak liczyć przesunięcie bitowe dla liczb ujemnych???
    7>>2 sobie przesunę na kartce rozpisując zera i jedynki 00000111 dwa w prawo da 1, ale -7>>2 ???? Jak się zapisuje -7? Jakiś bit rezerwujemy na znak?

    Nigdzie nie widzę w sieci przesuwania cyfr ujemnych...

    Będę wdzięczny za pomoc,

    Pozdrawiam

    0
  • #10 02 Gru 2011 12:43
    dioda1000
    Poziom 27  

    Cytat:
    Jak się zapisuje -7? Jakiś bit rezerwujemy na znak?

    11111000 = -7 'podkreślone to znak'

    poz.dioda

    0
  • #11 02 Gru 2011 12:58
    labo
    Poziom 13  

    dioda1000 napisał:
    Cytat:
    Jak się zapisuje -7? Jakiś bit rezerwujemy na znak?

    11111000 = -7 'podkreślone to znak'

    poz.dioda



    Uuu, moment.....
    Skoro 7 to 00000111
    7>>2 to 00000001

    A skąd się wzięło 11111000 = -7 ???

    0
  • #12 02 Gru 2011 15:32
    dioda1000
    Poziom 27  

    labo napisał:
    Jak się zapisuje -7? Jakiś bit rezerwujemy na znak?

    Sory masz rację popełniłem błąd.

    Poprawny zapis liczby ujemnej w bajcie.
    11111001 = -7 'podkreślone to znak' poprawnie
    11111000 = -8

    poz.dioda

    0
  • #13 02 Gru 2011 16:52
    labo
    Poziom 13  

    Chyba nie rozumiem...
    Jaka jest zasada zapisywania liczb ujemnych? -1 i -2 jak będą?

    0
  • #14 02 Gru 2011 17:22
    BoskiDialer
    Poziom 34  

    Operacja zmiany znaku polega na zanegowaniu wszystkich bitów i powiększeniu wartości o 1. Stąd 1 ma postać '0001', a -1 to '1111' ('0001' -> '1110' -> '1111'). Z poziomu języka C, spełniona jest równość (-x) == (~x + 1). To z takich prostych faktów.

    Co do przesunięcia w prawo, wyróżnia się zasadniczo dwa przesunięcia w prawo: logiczne (wolne miejsca wypełniane są zerami), oraz arytmetyczne (powielanie bitu znaku). Na mikrokontrolerach AVR istnieją do tego dwie osobne instrukcje: LSR (przesunięcie logiczne) oraz ASR (przesunięcie arytmetyczne). Na ARM'ach (bazując na dokumentacji do arm7tdmi) drugi operand do instrukcji przetwarzania może przejść przez LSR (przesunięcie logiczne) lub ASR (przesunięcie arytmetyczne). Na x86 do przesunięcia w prawo jest SHR (logiczne) oraz SAR (arytmetyczne). Szukając przez google, mikrokontrolery PIC (z tych większych) posiadają LSRF oraz ASRF.

    Z tego co ja się przynajmniej orientuję, to kompilatory języka C używają przesunięcia logicznego w prawo, jeśli przesuwa się liczbę bez znaku, a przesunięcia arytmetycznego, gdy przesuwa się liczbę ze znakiem.

    -- edit:
    Jeśli przesunięcie w prawo zmiennej ze znakiem nie działa tak jak powinno, można zrobić obejście typu:

    Kod: C
    Zaloguj się, aby zobaczyć kod

    0