Các số nguyên được biểu diễn bên trong như thế nào ở mức bit trong Java?


83

Tôi đang cố gắng hiểu cách Java lưu trữ số nguyên bên trong. Tôi biết tất cả các số nguyên nguyên thủy của java đều được ký, (ngoại trừ short?). Điều đó có nghĩa là một số ít hơn có sẵn trong một byte cho số.

Câu hỏi của tôi là, tất cả các số nguyên (dương và âm) được lưu trữ dưới dạng phần bù của hai hay chỉ là số âm trong phần bù của hai?

Tôi thấy rằng các thông số kỹ thuật nói x bit two's complement number. Nhưng tôi thường bị nhầm lẫn.

Ví dụ:

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

Biên tập

Để rõ ràng, x = 15

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

Vì vậy, nếu câu trả lời của bạn là các allsố được lưu trữ dưới dạng phần bù của hai thì:

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

Sự nhầm lẫn ở đây một lần nữa là dấu hiệu cho biết, cả hai đều là số âm. Có thể tôi đang đọc sai / hiểu sai nó?

Chỉnh sửa Không chắc câu hỏi của tôi khó hiểu. Buộc phải cô lập câu hỏi:

Câu hỏi của tôi chính xác là: Các số dương có được lưu trữ trong binary as iskhi các số âm được lưu trữ dưới dạng two's complementkhông?

Một số người nói rằng tất cả được lưu trữ trong phần bù của hai và một câu trả lời cho biết chỉ số âm được lưu trữ dưới dạng phần bù của hai.


Phần bù của hai nhất thiết có nghĩa là các số dương được biểu diễn bằng các giá trị bit thực của số đó ... ít nhất là theo tôi hiểu. CHỈNH SỬA: Ngoài ra, lời khen của hai có nghĩa là ít hơn một bit trong tổng số byte trong nguyên thủy, chứ không phải một byte PER ít hơn một bit.
LJ2

giả định của bạn là đúng: số dương và số âm là phần bù của hai, và của bạn xyđúng.
jlordo

Một lưu ý phụ: đó là một cái gì đó của WTF, Java, một ngôn ngữ của thời đại Internet, không có kiểu dữ liệu để đại diện, ví dụ. Số cổng TCP / IP (giá trị 16 bit không được đánh dấu) chính xác, đôi khi dẫn đến mã thực sự xấu xí.
hyde

kiểm tra bài viết wiki en.wikipedia.org/wiki/… số bổ sung của 2 bạn đưa ra cho 15 là sai
Dungeon Hunter

@hyde 'Mã thực sự xấu' chẳng hạn?
Marquis of Lorne,

Câu trả lời:


102

Hãy bắt đầu bằng cách tóm tắt các kiểu dữ liệu nguyên thủy của Java:

byte : Kiểu dữ liệu byte là một số nguyên bổ sung 8 bit có dấu của hai .

Ngắn : Kiểu dữ liệu ngắn là số nguyên bổ sung 16 bit có dấu của hai .

int: Kiểu dữ liệu int là số nguyên bổ sung 32-bit có dấu của hai .

long: Kiểu dữ liệu dài là số nguyên bổ sung 64 bit có dấu của hai .

float: Kiểu dữ liệu float là một dấu chấm động IEEE 754 32 bit chính xác đơn .

double : kiểu dữ liệu kép là dấu phẩy động IEEE 754 64 bit chính xác kép .

boolean: kiểu dữ liệu boolean đại diện cho một bit thông tin .

char:kiểu dữ liệu char char là một ký tự Unicode 16-bit .

Nguồn

Bổ sung của hai

"Ví dụ điển hình là từ wiki rằng mối quan hệ với phần bù của hai được nhận ra bằng cách lưu ý rằng 256 = 255 + 1 và (255 - x) là phần bù của x

0000 0111 = 7 phần bù của hai là 1111 1001 = -7

cách nó hoạt động là MSB (bit quan trọng nhất) nhận giá trị âm nên trong trường hợp trên

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

Số nguyên dương thường được lưu trữ dưới dạng số nhị phân đơn giản (1 là 1, 10 là 2, 11 là 3, v.v.).

Các số nguyên âm được lưu trữ dưới dạng phần bù của hai giá trị tuyệt đối của chúng. Phần bù của hai số dương khi sử dụng ký hiệu này là số âm.

Nguồn

Vì tôi đã nhận được một vài điểm cho câu trả lời này, tôi quyết định bổ sung thêm thông tin cho nó.

Một câu trả lời chi tiết hơn:

Trong số khác, có bốn cách tiếp cận chính để biểu diễn số dương và số âm trong hệ nhị phân, đó là:

  1. Tầm quan trọng đã ký
  2. Sự bổ sung của một
  3. Sự bổ sung của hai
  4. Thiên kiến

1. Độ lớn đã ký

Sử dụng bit quan trọng nhất để biểu diễn dấu hiệu, các bit còn lại được sử dụng để biểu diễn giá trị tuyệt đối. Trong đó 0 đại diện cho một số dương1 đại diện cho một số âm , ví dụ:

1011 = -3
0011 = +3

Biểu diễn này đơn giản hơn. Tuy nhiên, bạn không thể thêm số nhị phân giống như cách bạn thêm số thập phân, điều này khó thực hiện hơn ở cấp phần cứng. Hơn nữa, cách tiếp cận này sử dụng hai mẫu nhị phân để đại diện cho 0, 100 ... 0 và 0 .... 0.

2. Sự bổ sung của một

Trong biểu diễn này, chúng tôi đảo ngược tất cả các bit của một số nhất định để tìm ra phần bù của nó. Ví dụ:

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

Vấn đề của biểu diễn này là vẫn tồn tại hai mẫu bit để biểu diễn 0 (00..0 và 11..1)

3. Sự bổ sung của hai

Để tìm số âm của một số, trong biểu diễn này, chúng tôi đảo ngược tất cả các bit và sau đó thêm một bit. Thêm một bit giải quyết vấn đề có hai mẫu bit đại diện cho 0. Trong biểu diễn này, chúng ta chỉ có một (00 ... 0).

Ví dụ, chúng ta muốn tìm biểu diễn âm nhị phân của 4 (thập phân) bằng cách sử dụng 4 bit. Đầu tiên, chúng tôi chuyển đổi 4 thành nhị phân:

4 = 0100

sau đó chúng tôi đảo ngược tất cả các bit

0100 -> 1011

cuối cùng, chúng tôi thêm một chút

1011 + 1 = 1100.

Vì vậy, 1100 tương đương với -4 ở dạng thập phân nếu chúng ta đang sử dụng biểu diễn nhị phân Bổ sung Hai với 4 bit.

Một cách nhanh hơn để tìm phần bổ sung là cố định bit đầu tiên là giá trị 1 và đảo các bit còn lại. Trong ví dụ trên, nó sẽ giống như sau:

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

Biểu diễn bổ sung của Two, ngoài việc chỉ có một biểu diễn cho 0, nó còn thêm vào hai giá trị nhị phân theo cách giống như ở dạng thập phân, số chẵn có các dấu khác nhau. Tuy nhiên, cần phải kiểm tra các trường hợp tràn.

4. Sự thiên vị

Biểu diễn này được sử dụng để biểu diễn số mũ trong tiêu chuẩn IEEE 754 cho dấu chấm động. Nó có ưu điểm là giá trị nhị phân với tất cả các bit đến 0 đại diện cho giá trị nhỏ nhất. Và giá trị nhị phân với tất cả các bit đến 1 đại diện cho giá trị lớn nhất. Như tên cho biết, giá trị được mã hóa (dương hoặc âm) ở dạng nhị phân với n bit có độ lệch (thường là 2 ^ (n-1) hoặc 2 ^ (n-1) -1).

Vì vậy, nếu chúng ta đang sử dụng 8 bit, giá trị 1 ở dạng thập phân được biểu diễn ở dạng nhị phân sử dụng độ lệch 2 ^ (n-1), bởi giá trị:

+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001

2
Câu hỏi của tôi chính xác: Các số + ve có được lưu trữ trong các binary as issố -ve được lưu trong two's complementkhông?
Kevin Rave,

1
Số nguyên dương thường được lưu trữ dưới dạng số nhị phân đơn giản và số nguyên âm được lưu trữ dưới dạng phần bù của hai số.
dreamcrash

Điều đó trả lời câu hỏi của tôi. Nguồn nào không? Tôi không tìm thấy tài liệu nào nói rõ điều này.
Kevin Rave,

liên kết trên từ ecomware.com @dreamcrash bị hỏng, bạn có thể cung cấp một số liên kết khác không?
Ram Patra

@Ramswaroop Xin chào, còn cái này thì sao về cái này stackoverflow.com/questions/1049722/what-is-2s-complement
dreamcrash

61

Số nguyên Java có 32 bit và luôn có dấu. Điều này có nghĩa là, bit quan trọng nhất (MSB) hoạt động như là bit dấu. Số nguyên được biểu diễn bởi an intkhông là gì ngoài tổng trọng số của các bit. Các trọng số được ấn định như sau:

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

Lưu ý rằng trọng số của MSB là âm (thực tế là âm lớn nhất có thể), vì vậy khi bit này được bật, toàn bộ số (tổng có trọng số) trở thành âm.

Hãy mô phỏng nó với các số 4 bit:

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

Vì vậy, điều bổ sung của cả hai không phải là một lược đồ độc quyền để biểu diễn số nguyên âm, đúng hơn chúng ta có thể nói rằng biểu diễn nhị phân của số nguyên luôn giống nhau, chúng ta chỉ phủ định trọng số của bit quan trọng nhất. Và bit đó xác định dấu của số nguyên.

Trong C, có một từ khóa unsigned(không có trong java), có thể dùng để khai báo unsigned int x;. Trong các số nguyên không dấu, trọng số của MSB là dương ( 2^31) thay vì âm. Trong trường hợp đó, phạm vi của một unsigned int0đến 2^32 - 1, trong khi một intcó phạm vi -2^312^31 - 1.

Từ một quan điểm khác, nếu bạn coi phần bù của hai x~x + 1(KHÔNG phải x cộng với một), đây là lời giải thích:

Đối với bất kỳ x, ~xchỉ là nghịch đảo của bit x, vì vậy bất cứ nơi nào x1-bit, ~xsẽ có 0-bit ở đó (và ngược lại). Vì vậy, nếu bạn cộng những thứ này lên, sẽ không có giá trị nào trong phép cộng và tổng sẽ chỉ là một số nguyên mỗi bit của nó 1.

Đối với số nguyên 32 bit:

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

-Bit ngoài cùng bên trái 1sẽ đơn giản bị loại bỏ vì nó không vừa với 32-bit (tràn số nguyên). Vì thế,

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

Vì vậy, bạn có thể thấy rằng phủ định xcó thể được biểu diễn bằng ~x + 1, mà chúng tôi gọi là phần bù của cả hai x.


Câu hỏi của tôi chính xác: Các số + ve có được lưu trữ trong các binary as issố -ve được lưu trữ trong two's complementkhông?
Kevin Rave,

Vâng, vâng. một số âm được biểu diễn trên máy tính dưới dạng phần bù của hai giá trị dương của nó.
0605002

4
Great câu trả lời và giải thích Bonny @ 0605002, 1 :)
KM Rakibul Hồi giáo

@ 0605002: Bạn có thể vui lòng cung cấp tài liệu tham khảo cho câu trả lời này, nếu có? Mặc dù tôi biết các khái niệm nhưng chưa bao giờ thực sự nghĩ chúng theo cách đó. Câu trả lời đơn giản nhất, vẫn chính xác.
Abhishek Singh

Bốn năm đại học, và tôi chưa bao giờ hiểu bổ sung 2s. Câu trả lời này đã dạy tôi nhiều hơn. Thật đáng buồn khi những điều đơn giản như vậy lại được dạy theo những cách khó hiểu như vậy trên khắp thế giới.
Prashant Pandey

10

Tôi đã chạy chương trình sau để biết nó

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));
    }
}

Đầu ra là

1010
11111111111111111111111111110110

Từ đầu ra, có vẻ như nó đã được sử dụng phần bổ sung của hai.


1
Phần bù Twos của 10 là 11111111 11111111 11111111 11110110. Bản in của bạn trong khi Binary như đối với 10 là 1010. Vậy chỉ số -ve được lưu trữ dưới dạng phần bù của hai?
Kevin Rave,

kiểm tra bài viết wiki en.wikipedia.org/wiki/…, số bổ sung của 2 bạn đưa ra cho 15 là sai
Dungeon Hunter

nếu các bit MSB bắt đầu với 1 nó sẽ là số âm
Dungeon Hunter

vâng hai của bổ sung của 10 là 11111111 11111111 11111111 11.110.110 đó là -10
Dungeon Hunter

ve con số sẽ được lưu dưới dạng nhị phân để lại chút dấu trong bổ sung 2 của
Dungeon Hunter

4

Oracle cung cấp một số tài liệu về Kiểu dữ liệu Java mà bạn có thể thấy thú vị. Đặc biệt:

int: Kiểu dữ liệu int là số nguyên bổ sung 32-bit có dấu của hai. Nó có giá trị tối thiểu là -2,147,483,648 và giá trị lớn nhất là 2,147,483,647 (bao gồm).

Btw, ngắn cũng được lưu trữ dưới dạng bổ sung của hai.


3

Theo tài liệu này , tất cả các số nguyên được ký và lưu trữ ở định dạng bổ sung hai cho java. Không chắc chắn về độ tin cậy của nó ..


"Trong định dạng bổ sung của hai, một giá trị dương được biểu diễn dưới dạng số nhị phân đơn giản." được viết trong cùng một tài liệu .. vì vậy về mặt kỹ thuật thì nó chính xác. :)
Shashi

3

Các số dương được lưu trữ / truy xuất như nó vốn có.

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. 

Nhưng các số âm sẽ được lưu trữ sau phần bù của 2 (khác với bit MSB), và bit MSB sẽ được đặt thành 1.

ví dụ) khi lưu trữ -10 thì

  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

khi truy xuất, nó thấy rằng MSB được đặt thành 1. Vì vậy, nó là số âm không. Và phần bổ sung của 2 sẽ được thực hiện khác với MSB.

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

Vật đúc

Cũng lưu ý rằng khi bạn đang truyền int / short sang byte, chỉ byte cuối cùng sẽ được xem xét cùng với byte MSB cuối cùng,

Lấy ví dụ ngắn "-130", nó có thể được lưu trữ như bên dưới

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

Bây giờ truyền byte lấy byte cuối cùng là 0111 1110. (0-MSB) Vì MSB cho biết đó là giá trị + ve, vì vậy nó sẽ được lấy như cũ. Đó là 126. (+ ve).

Lấy một ví dụ khác ngắn gọn là "130", nó có thể được lưu trữ như bên dưới

  0-000 000 1000 0010     (MSB = 0)

Bây giờ truyền byte lấy byte cuối cùng là 1000 0010. (1 = MSB) Vì MSB cho biết đó là giá trị -ve, phần bù của 2 sẽ được thực hiện và số âm sẽ được trả về. Vì vậy, trong trường hợp này -126 sẽ được trả về.

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

Chênh lệch giữa (int) (char) (byte) -1 AND (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) 

tương tự

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

Nhưng

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

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

Người giới thiệu

Tại sao phần bù của hai được dùng để biểu diễn các số âm?

"Bổ sung 2" là gì?



2

Bit quan trọng nhất (thứ 32) cho biết số đó là số dương hoặc số âm. Nếu nó là 0, nó có nghĩa là số dương và nó được lưu trữ trong biểu diễn nhị phân thực tế của nó. nhưng nếu nó là 1, nó có nghĩa là số âm và được lưu trữ trong biểu diễn phần bù hai của nó. Vì vậy, khi chúng tôi đưa trọng số -2 ^ 32 cho bit thứ 32 trong khi khôi phục giá trị số nguyên từ biểu diễn nhị phân của nó, Chúng tôi nhận được câu trả lời thực tế.


1
Chào mừng bạn đến với StackOverflow! : D
0605002

2

Cảm ơn bạn, dreamcrash về câu trả lời https://stackoverflow.com/a/13422442/1065835 ; trên trang wiki, họ đưa ra một ví dụ giúp tôi hiểu cách tìm ra cách biểu diễn nhị phân của phần đối âm của một số dương.

Ví dụ: sử dụng 1 byte (= 2 nibbles = 8 bit), số thập phân 5 được biểu thị bằng

0000 01012 Bit quan trọng nhất là 0, vì vậy mẫu biểu thị một giá trị không âm. Để chuyển đổi thành −5 trong ký hiệu hai phần bù, các bit được đảo ngược; 0 trở thành 1 và 1 trở thành 0:

1111 1010 Tại thời điểm này, chữ số là phần bù của giá trị thập phân −5. Để có được phần bù của cả hai, 1 được thêm vào kết quả, tạo ra:

1111 1011 Kết quả là một số nhị phân có dấu biểu thị giá trị thập phân −5 ở dạng phần bù của hai. Bit quan trọng nhất là 1, vì vậy giá trị được biểu diễn là âm.


1

số dương được lưu trữ trực tiếp dưới dạng nhị phân. Lời khen của 2 là bắt buộc đối với số âm.

ví dụ:

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

đây là sự khác biệt trong bit đã ký.


1

Đối với số nguyên dương 2 'giá trị hoàn thành giống với bit 0 của MSB (like +14 2'complement is 01110).

Đối với chỉ số nguyên âm, chúng tôi đang tính giá trị 2'complement (-14= 10001+1 = 10010).

Vì vậy, câu trả lời cuối cùng là cả hai giá trị (+ve and -ve)chỉ được lưu trữ ở dạng 2'complement.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.