logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

C18: Przesunięcie bitowe liczby ujemnej w lewo z dopełnieniem jedynkami

wilk125 21 Paź 2011 15:53 3788 13
REKLAMA
  • #1 10050428
    wilk125
    Poziom 23  
    Posty: 912
    Pomógł: 17
    Ocena: 44
    Witam
    Kompilator C18.
    Mam liczbę int, która jest ujemna i chce ją przesunać o 4 miejsca w lewo:
    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
  • REKLAMA
  • #2 10050575
    dondu
    VIP Zasłużony dla elektroda
    Posty: 13906
    Pomógł: 1292
    Ocena: 809
    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ć.
  • REKLAMA
  • Pomocny post
    #3 10050576
    megao
    Poziom 25  
    Posty: 690
    Pomógł: 66
    Ocena: 90
    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?
  • Pomocny post
    #4 10054172
    Konto nie istnieje
    Konto nie istnieje  
  • #5 10059764
    wilk125
    Poziom 23  
    Posty: 912
    Pomógł: 17
    Ocena: 44
    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
  • REKLAMA
  • #6 10061306
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #7 10062907
    dioda1000
    Poziom 28  
    Posty: 833
    Pomógł: 143
    Ocena: 131
    Witam
    Zaciekawił mnie ten temat .Też ciekaw jestem jak inne kompilatory to rozwiążą.
    int a=-34;
    long b;
    b=(long)a>>4;

    Kod: text
    Zaloguj się, aby zobaczyć kod


    poz. dioda
  • #8 10063569
    Konto nie istnieje
    Konto nie istnieje  
  • #9 10206421
    labo
    Poziom 13  
    Posty: 300
    Pomógł: 2
    Ocena: 16
    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
  • #10 10208864
    dioda1000
    Poziom 28  
    Posty: 833
    Pomógł: 143
    Ocena: 131
    Cytat:
    Jak się zapisuje -7? Jakiś bit rezerwujemy na znak?

    11111000 = -7 'podkreślone to znak'

    poz.dioda
  • #11 10208916
    labo
    Poziom 13  
    Posty: 300
    Pomógł: 2
    Ocena: 16
    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 ???
  • #12 10209465
    dioda1000
    Poziom 28  
    Posty: 833
    Pomógł: 143
    Ocena: 131
    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
  • #13 10209777
    labo
    Poziom 13  
    Posty: 300
    Pomógł: 2
    Ocena: 16
    Chyba nie rozumiem...
    Jaka jest zasada zapisywania liczb ujemnych? -1 i -2 jak będą?
  • #14 10209901
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    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: text
    Zaloguj się, aby zobaczyć kod

Podsumowanie tematu

✨ W dyskusji poruszono problem przesunięcia bitowego liczby ujemnej w lewo w kompilatorze C18. Użytkownik chciał przesunąć liczbę int (-34) o 4 miejsca w lewo, jednak napotkał problem z dopełnieniem, które w C18 jest realizowane zerami, co nie odpowiada jego oczekiwaniom. Uczestnicy dyskusji zasugerowali różne podejścia, w tym użycie operacji dzielenia przez 2^n jako alternatywy dla przesunięcia bitowego. Zwrócono uwagę na różnice w implementacji przesunięć w różnych kompilatorach oraz na to, że przesunięcia bitowe dla liczb ujemnych mogą być zdefiniowane w sposób zależny od implementacji. Wspomniano również o technikach zapisu liczb ujemnych oraz o różnicy między przesunięciem logicznym a arytmetycznym.
Wygenerowane przez model językowy.
REKLAMA