JavaRush /Blog Java /Random-VI /Phủ định theo bit - tại sao lại như vậy?
Alex Bolgov
Mức độ
Ташкент

Phủ định theo bit - tại sao lại như vậy?

Xuất bản trong nhóm
Xin chào mọi người :) Khi đọc bài viết Phép toán Bitwise, tôi cũng như một số người khác, có một câu hỏi: tại sao khi đảo ngược số 342, chúng ta lại nhận được -343. Trong bài viết nó trông như thế này: Phủ định theo bit - tại sao vậy - 1Những người đặc biệt tò mò (như tôi) có một câu hỏi: "Này, nhưng 010101001 nhỏ hơn 101010110, theo logic thì nó phải nhỏ hơn 342 và là số dương." Bằng cách nhập nó vào bất kỳ công cụ chuyển đổi số trực tuyến nào hoặc kiểm tra nó bằng mã:
Integer a = Integer.valueOf("010101001", 2);
System.out.println(Integer.toString(a, 10));
thật bất ngờ là chúng tôi nhận được thứ gì đó khác ngoài -343...
169
Ôi, thật tốt biết bao khi ngày xưa, trong một lớp học về lập trình C, bằng cách nào đó tôi đã nghe thoáng qua điều gì đó về dấu hiệu trong số nguyên. Sau khi tìm kiếm trên Google một lúc, bây giờ tôi có thể giải thích đây là loại động vật gì. Phủ định theo bit - tại sao vậy - 2Thực ra bài viết có chỗ sai sót, gây khó hiểu. Nếu chúng ta kiểm tra bằng mã, kết quả thực sự của việc đảo ngược số 342 là gì:
int a = 342;
System.out.println(Integer.toBinaryString(~a));
sau đó chúng ta sẽ thấy một kết quả hơi khác một chút
1111111111111111111111010101001
Tại sao cái này rất? Vấn đề là một biến không thể đơn giản chứa 101010110; trên thực tế, nó được lưu trữ dưới dạng
000000000000000000000000101010110
Rốt cuộc, một biến int có 4 byte, tức là 32 bit - 32 ô nhớ. Sau khi đảo ngược, tất cả các số đều thay đổi, tức là và "cắt bớt" các số 0 đứng đầu. Bây giờ đến phần thú vị. Vì trong biểu diễn nhị phân, dấu + hoặc - ở phía trước một số không thể được lưu trữ nên có một mẹo: bit đầu tiên thực sự chịu trách nhiệm về dấu và chính xác là bit dấu . Và tất cả các số được lưu trữ theo logic này: các số từ 00...000 đến 01...111 đều dương, bắt đầu từ 0 (tức là từ 0 đến 2147483647) và bắt đầu từ 10...000 đến 11... 111 là số âm, bắt đầu từ số nhỏ nhất và kết thúc bằng -1 (tức là -2147483648 đến -1).
00000000000000000000000000000000 = 0
01111111111111111111111111111111 = 2147483647
10000000000000000000000000000000 = -2147483648
11111111111111111111111111111111 = -1
Và sau đó bạn hỏi, "Được rồi, Navalny, chúng tôi sẽ tin bạn, nhưng tại sao bạn lại quyết định rằng đây là cung điện của anh ấy," nhưng làm thế nào mà nó lại trở thành -343 với tất cả những điều này? Nó thực sự đơn giản. Chúng ta có thể đơn giản tính toán điều này bằng tay. Nếu chúng ta “cắt bỏ” (hoặc thay thế bằng 0) bit đầu tiên từ phiên bản nhị phân của số kết quả 342 ( 1111111111111111111111111111111111111111010101001 ) và đưa nó trở lại dạng thập phân.
String s = "01111111111111111111111010101001";
System.out.println(s + " = " + Integer.toString(Integer.valueOf(s, 2), 10));
sau đó chúng ta hiểu được điều đó
0111111111111111111111010101001 = 2147483305
Trên thực tế, ở đây chúng ta không chỉ "cắt bỏ" 1 ngay từ đầu mà còn trừ 100000000000000000000000000000000000 từ số này. Bây giờ chúng ta hãy cộng lại, nhưng ở dạng thập phân. Những gì chúng ta sẽ thấy:
~342 =
11111111111111111111111010101001 =
//в двоичном виде//
01111111111111111111111010101001 +
10000000000000000000000000000000
=
//в десятичном виде//
-2147483648 + 2147483305 = -343
Đây là số bắt buộc -343 :) Các bạn ơi, đây là bài đăng đầu tiên của tôi ở đây, hãy thích nó nếu bạn thích và nó mang tính thông tin (tôi thực sự muốn thu thập tất cả thành tích 😄) Bạn có thể đọc thêm về chủ đề này tại đây: Chúc mọi người may mắn và cảm ơn đã quan tâm)
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION