W jaki sposób liczby całkowite są wewnętrznie reprezentowane na poziomie bitów w Javie?

Próbuję zrozumieć, w jaki sposób Java przechowuje wewnętrznie liczbę całkowitą. Wiem, że wszystkie Java primitive integers są podpisane, (poza krótkimi?). Oznacza to, że jeden bit mniej dostępny w bajcie dla liczby.

Moje pytanie brzmi, czy wszystkie liczby całkowite (dodatnie i ujemne) są przechowywane jako dopełniacz dwójki, czy tylko liczby ujemne w dopełniaczu dwójki?

Widzę, że specyfikacje mówią x bit two's complement number. Ale często się mylę.

Na przykład:

  int x = 15; // Stored as binary as is?  00000000 00000000 00000000 00001111?
  int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010

Edit

Żeby było jasne, x = 15

   In binary as is: `00000000 00000000 00000000 00001111'
  Two's complement: `11111111 11111111 11111111 11110001`

Więc jeśli Twoja odpowiedź to all liczby są zapisywane jako dopełniacz dwójki to:

  int x = 15; // 11111111 11111111 11111111 11110001
  int y = -22 // 11111111 11111111 11111111 11101010

Zamieszanie tutaj znowu jest znak mówi, oba są liczbami ujemnymi. Może źle to odczytałem / źle zrozumiałem?

Edit Nie jestem pewien, czy moje pytanie jest mylące. Zmuszony do wyizolowania pytania:

Moje pytanie brzmi dokładnie: czy liczby dodatnie są przechowywane w binary as is, podczas gdy liczby ujemne są przechowywane jako two's complement?

Niektórzy mówili, że wszystkie są przechowywane w dwóch dopełnienie i jedna odpowiedź mówi, że tylko liczby ujemne są przechowywane jako dopełnienie dwóch.

Author: ArtB, 2012-11-16

10 answers

Zacznijmy od podsumowania prymitywnych typów danych Javy:

Byte : typ danych Byte jest 8-bitową liczbą całkowitą dopełniacza two.

Short : typ danych Short jest 16-bitową, podpisaną liczbą całkowitą dopełniacza Dwójki .

Int: typ danych Int jest 32-bitową, podpisaną liczbą całkowitą dopełniacza Dwójki.

Long: typ danych Long jest 64-bitową, podpisaną liczbą całkowitą dopełniacza Dwójki .

Float: Float typ danych jest jednoprzecinkowy 32-bitowy zmiennoprzecinkowy IEEE 754.

Double : typ danych double jest 64-bitowym zmiennoprzecinkowym IEEE 754 o podwójnej precyzji .

Boolean: typ danych boolean reprezentuje jeden bit informacji.

Char: typ danych char to pojedynczy 16-bitowy znak Unicode.

Źródło

Dopełniacz Dwójki

"dobry przykład jest z wiki że relacja do dopełnienia dwójki jest realizowana przez zauważenie, że 256 = 255 + 1, oraz (255-x) jest dopełnieniem jedynek z x

0000 0111=7 dopełniacz dwójki to 1111 1001= -7

Sposób działania polega na tym, że msb(najbardziej znaczący bit) otrzymuje wartość ujemną, więc w powyższym przypadku

-7 = 1001= -8 + 0+ 0+ 1

Dodatnie liczby całkowite są zwykle przechowywane jako proste liczby binarne(1 to 1, 10 to 2, 11 to 3 i tak dalej).

Negatywny liczby całkowite są przechowywane jako dopełnienie ich wartości bezwzględnej. Dopełnienie liczby dodatniej jest przy użyciu tej notacji liczbą ujemną.

Źródło

Ponieważ otrzymałem kilka punktów za tę odpowiedź, postanowiłem dodać więcej informacji.

Bardziej szczegółowa odpowiedź:

Istnieją między innymi cztery główne podejścia do reprezentowania liczb dodatnich i ujemnych w binarnych, a mianowicie:

  1. podpisane Magnitude
  2. dopełniacz
  3. dopełniacz dwójki
  4. Bias

1. Signed Magnitude

Używa najbardziej znaczącego bitu do reprezentowania znaku, pozostałe bity są używane do reprezentowania wartości bezwzględnej. Gdzie 0 reprezentuje liczbę dodatnią i 1 reprezentuje liczbę ujemną , przykład:

1011 = -3
0011 = +3

Ta reprezentacja jest prostsza. Nie można jednak dodawać liczb binarnych w ten sam sposób że dodajesz liczby dziesiętne, co utrudnia implementację na poziomie sprzętowym. Co więcej, to podejście wykorzystuje dwa binarne wzorce do reprezentowania 0, 100...0 i 0....0.

2. Dopełniacz

W tej reprezentacji odwracamy wszystkie bity danej liczby, aby znaleźć jej komplementarność. Dla exemple:

010 = 2, so -2 = 101 (inverting all bits).

Problem tej reprezentacji polega na tym, że nadal istnieją dwa wzorce bitów, które reprezentują 0 (00..0 i 11..1)

3. Dopełniacz Dwójki

Aby znaleźć ujemną liczbę, w tej reprezentacji odwracamy wszystkie bity, a następnie dodajemy jeden bit. Dodanie jednego bitu rozwiązuje problem posiadania dwóch bitów reprezentujących 0. W reprezentacji tej mamy tylko jedną (00 ...0).

Dla exemple chcemy znaleźć binarną negatywną reprezentację 4 (dziesiętną) za pomocą 4 bitów. Najpierw przekonwertujemy 4 na binarne:

4 = 0100

Następnie odwracamy wszystkie bity

0100 -> 1011

Wreszcie dodajemy jeden bit

1011 + 1 = 1100.

Więc 1100 jest równoważne -4 w układzie dziesiętnym, jeśli używamy reprezentacji binarnej dopełniacza dwójki z 4 bitami.

Szybszym sposobem znalezienia komplementarności jest ustalenie pierwszego bitu, który ma wartość 1 i odwrócenie pozostałych bitów. W powyższym przykładzie byłoby to coś w stylu:

0100 -> 1100
^^ 
||-(fixing this value)
|--(inverting this one)

Reprezentacja dopełniacza dwójki, poza tym, że ma tylko jedną reprezentację dla 0, dodaje również dwie wartości binarne w ten sam sposób, że w dziesiętnych, parzystych liczbach o różnych znaki. Niemniej jednak konieczne jest sprawdzenie przypadków przepełnienia.

4. Bias

Ta reprezentacja jest używana do reprezentowania wykładnika w normie IEEE 754 dla punktów zmiennoprzecinkowych. Ma tę zaletę, że wartość binarna ze wszystkimi bitami do zera reprezentuje najmniejszą wartość. A wartość binarna ze wszystkimi bitami do 1 reprezentuje największą wartość. Jak sama nazwa wskazuje, wartość jest zakodowana (dodatnia lub ujemna) w układzie binarnym z n bitami z odchyleniem (zwykle 2^(n-1) lub 2^(n-1)-1).

Więc jeśli używamy 8 bitów, wartość 1 w dziesiętnym jest reprezentowana w binarnym przy użyciu odchylenia 2^(n-1), przez wartość:

+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
 77
Author: dreamcrash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:14

Liczby całkowite Javy są 32-bitowe i zawsze podpisane. Oznacza to, że najbardziej znaczący bit (MSB) działa jako bit znaku. Liczba całkowita reprezentowana przez int jest niczym innym jak ważoną sumą bitów. Wagi są przypisane w następujący sposób:

Bit#    Weight
31      -2^31
30       2^30
29       2^29
...      ...
2        2^2
1        2^1
0        2^0

Zauważ, że waga MSB jest ujemna (największa możliwa ujemna w rzeczywistości), więc gdy ten bit jest włączony, liczba całkowita (suma ważona) staje się ujemna.

Let ' s simulate it with 4-bit liczby:

Binary    Weighted sum            Integer value
0000       0 + 0 + 0 + 0           0
0001       0 + 0 + 0 + 2^0         1
0010       0 + 0 + 2^1 + 0         2
0011       0 + 0 + 2^1 + 2^0       3
0100       0 + 2^2 + 0 + 0         4
0101       0 + 2^2 + 0 + 2^0       5
0110       0 + 2^2 + 2^1 + 0       6
0111       0 + 2^2 + 2^1 + 2^0     7 -> the most positive value
1000      -2^3 + 0 + 0 + 0        -8 -> the most negative value
1001      -2^3 + 0 + 0 + 2^0      -7
1010      -2^3 + 0 + 2^1 + 0      -6
1011      -2^3 + 0 + 2^1 + 2^0    -5
1100      -2^3 + 2^2 + 0 + 0      -4
1101      -2^3 + 2^2 + 0 + 2^0    -3
1110      -2^3 + 2^2 + 2^1 + 0    -2
1111      -2^3 + 2^2 + 2^1 + 2^0  -1

Zatem dopełnienie tych dwóch rzeczy nie jest wyłącznym schematem przedstawiania ujemnych liczb całkowitych, raczej możemy powiedzieć, że binarna reprezentacja liczb całkowitych jest zawsze taka sama, po prostu negujemy wagę najbardziej znaczącego bitu. I ten bit określa znak liczby całkowitej.

W języku C istnieje słowo kluczowe unsigned (niedostępne w Javie), które może być użyte do zadeklarowania unsigned int x;. W niepodpisanych liczbach całkowitych masa MSB jest dodatnia (2^31), a nie bycie negatywnym. W tym przypadku zakres unsigned int wynosi 0 do 2^32 - 1, podczas gdy int mA Zakres -2^31 do 2^31 - 1.

Z innego punktu widzenia, jeśli rozważysz dopełniacz x jako ~x + 1 (nie x plus jeden), oto Wyjaśnienie:

Dla każdego x, ~x jest tylko bitową odwrotnością x, więc gdziekolwiek x mA 1-bit, ~x będzie miał 0-bit tam (i vice versa). Tak więc, jeśli dodasz je, nie będzie przenoszenia w dodatku i suma będzie tylko liczbą całkowitą, której każdy bit jest 1.

Dla 32-bitowych liczb całkowitych:

x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 =   1111 1111 1111 1111 1111 1111 1111 1111 + 1
           = 1 0000 0000 0000 0000 0000 0000 0000 0000

Lewy 1-bit zostanie po prostu odrzucony, ponieważ nie mieści się w 32-bitach (integer overflow).

x + ~x + 1 = 0
-x = ~x + 1

Więc widać, że negatyw x Może być reprezentowany przez ~x + 1, które nazywamy dopełnieniem obu x.

 52
Author: 0605002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-05 07:36:31

Uruchomiłem następujący program, aby go poznać

public class Negative {
    public static void main(String[] args) {
        int i =10;
        int j = -10;

        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(j));
    }
}

Wyjście To

1010
11111111111111111111111111110110

Z wyjścia wynika, że używa dopełniacza two.

 8
Author: Dungeon Hunter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-30 17:24:04

Oracle dostarcza pewną dokumentację dotyczącą typów danych Java , która może Cię zainteresować. Konkretnie:

Int: typ danych int jest 32-bitową, podpisaną liczbą całkowitą dopełniacza dwójki. Ma minimalną wartość -2,147,483,648 i maksymalną wartość 2,147,483,647 (włącznie).

Btw, short jest również zapisywany jako dopełnienie dwójki.

 3
Author: matsev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-16 18:35:49

Zgodnie z ten dokument , wszystkie liczby całkowite są podpisane i przechowywane w formacie uzupełniającym two dla Javy. Nie jestem pewien jego wiarygodności..

 3
Author: Joel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-04 19:20:35

Najbardziej znaczący bit (32nd) wskazuje, że liczba jest dodatnia lub ujemna. Jeśli jest to 0, oznacza to, że liczba jest dodatnia i jest przechowywana w jej rzeczywistej reprezentacji binarnej. ale jeśli jest 1, oznacza to, że liczba jest ujemna i jest przechowywana w reprezentacji dopełniacza jej dwóch. Tak więc, gdy podamy wagę -2^32 do 32-go bitu, przywracając wartość całkowitą z jego binarnej reprezentacji, otrzymujemy rzeczywistą odpowiedź.

 2
Author: Sazzadur Rahaman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-16 18:57:45

Thank you, dreamcrash for The answer https://stackoverflow.com/a/13422442/1065835 ; na stronie wiki dają przykład, który pomógł mi zrozumieć, jak znaleźć binarną reprezentację negatywnego odpowiednika liczby dodatniej.

Na przykład, używając 1 bajtu (=2 bajty = 8 bitów), liczba dziesiętna 5 jest reprezentowany przez

0000 01012 najbardziej znaczącym bitem jest 0, więc wzór reprezentuje wartość nieujemna. Na przeliczyć na -5 w notacji dopełniacza dwójkowego, czyli bity są odwrócone; 0 staje się 1, A 1 staje się 0:

1111 1010 wartość dziesiętna -5. Aby otrzymać dopełnienie dwóch, dodaje się 1 do wynik, dając:

1111 1011 wynikiem jest podpisana liczba binarna reprezentująca wartość dziesiętna -5 w postaci dopełniacza dwójki. Najbardziej znaczącym bitem jest 1, więc reprezentowana wartość jest ujemna.

 2
Author: Maksim Dmitriev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:06

Liczby dodatnie są przechowywane / pobierane tak, jak jest.

e.g) For +ve number 10; byte representation will be like 0-000 0010 
                                               (0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve, 
so the value will be taken as it is. 

Ale liczby ujemne będą zapisywane po dopełniaczu 2 (innym niż Bit MSB), a bit MSB zostanie ustawiony na 1.

Np. podczas przechowywania -10 wtedy

  0-000 0010  -> (1's complement) -> 0-111 1101 
              -> (2's complement) 0-111 1101 + 1 -> 0-111 1110
  Now MSB will be set to one, since it is negative no -> 1-111 1110

Podczas pobierania okazało się, że MSB jest ustawione na 1. Więc to jest negatywne nie. Dopełnienie 2 będzie wykonywane inaczej niż MSB.

  1-111 1110  --> 1-000 0001 + 1 --> 1-000 0010
  Since MSB representing this is negative 10 --> hence  -10 will be retrived.

Casting

Zauważ również, że podczas castingu int / short to byte, tylko ostatni bajt będzie brany pod uwagę wraz z ostatnim bajtem MSB,

Weźmy przykład "-130" w skrócie, może być przechowywany jak poniżej

(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110

Teraz casting bajtów wziął ostatni bajt, który jest 0111 1110. (0-MSB) Ponieważ MSB mówi, że jest to wartość + ve, więc zostanie ona przyjęta tak, jak jest. Czyli 126. (+ve).

Weźmy inny przykład " 130 " W skrócie, może być przechowywany jak poniżej

  0-000 000 1000 0010     (MSB = 0)

Teraz casting bajtów wziął ostatni bajt, który wynosi 1000 0010 . (1=MSB) Skoro MSB mówi, że jest - wartość ve, zostanie wykonane dopełnienie 2 i zostanie zwrócona liczba ujemna. Tak więc w tym przypadku -126 zostanie zwrócone.

 1-000 0010  -> (1's complement) -> 1-111 1101 
             -> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
               = -126

Różnica pomiędzy (int)(char) (byte) -1 i (int) (short) (byte) -1

(byte)-1       -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

Podobnie

(short)(byte)-1-> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

Ale

(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111  = 65535
since char is unsigned; MSB won't be carry forwarded. 

I

(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded. 

Referencje

Dlaczego dopełniacz two jest używany do reprezentowania liczb ujemnych?

Co To jest "dopełnienie 2"?

 2
Author: Kanagavelu Sugumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:17

Liczby dodatnie są zapisywane bezpośrednio jako binarne. Komplement 2 jest wymagany dla liczb ujemnych.

Na przykład:

15 : 00000000 00000000 00000000 00001111
-15: 11111111 11111111 11111111 11110001

Oto różnica w podpisanym bitie.

 1
Author: Siva Padhy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-07 06:59:52

Dla dodatniej liczby całkowitej 2 ' jest taka sama dla bitu MSB 0 (like +14 2'complement is 01110).

Tylko dla ujemnej liczby całkowitej obliczamy wartość 2 ' (-14= 10001+1 = 10010).

Więc ostateczną odpowiedzią jest to, że obie wartości (+ve and -ve) są przechowywane tylko w postaci 2'.

 1
Author: Mangesh Gawali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-27 17:50:00