Câu trả lời:
Hãy nhớ rằng các số âm được lưu trữ dưới dạng bổ sung của hai đối tác dương. Ví dụ, đây là biểu diễn của -2 trong phần bù hai: (8 bit)
1111 1110
Cách bạn có được điều này là bằng cách lấy biểu diễn nhị phân của một số, lấy phần bù của nó (đảo ngược tất cả các bit) và thêm một số. Hai bắt đầu là 0000 0010 và bằng cách đảo ngược các bit, chúng tôi nhận được 1111 1101. Thêm một cho chúng tôi kết quả ở trên. Bit đầu tiên là bit dấu, ngụ ý âm.
Vì vậy, hãy xem làm thế nào chúng ta nhận được ~ 2 = -3:
Đây là hai lần nữa:
0000 0010
Đơn giản chỉ cần lật tất cả các bit và chúng tôi nhận được:
1111 1101
Chà, -3 trông như thế nào trong phần bổ sung của hai? Bắt đầu với số dương 3: 0000 0011, lật tất cả các bit thành 1111 1100 và thêm một bit để trở thành giá trị âm (-3), 1111 1101.
Vì vậy, nếu bạn chỉ cần đảo ngược các bit trong 2, bạn sẽ có đại diện bổ sung của hai là -3.
~
lật các bit trong giá trị.
Tại sao ~2
là -3
đã làm với bao số được biểu diễn trên bit. Các số được biểu diễn dưới dạng bổ sung của hai .
Vì vậy, 2 là giá trị nhị phân
00000010
Và ~ 2 lật các bit để giá trị bây giờ là:
11111101
Trong đó, là biểu diễn nhị phân của -3.
Như những người khác đã đề cập, ~
chỉ lật các bit (thay đổi một thành 0 và 0 thành một) và vì hai phần bù được sử dụng, bạn nhận được kết quả mà bạn đã thấy.
Một điều cần nói thêm là tại sao hai phần bù được sử dụng, điều này là do các phép toán trên số âm sẽ giống như trên số dương. Hãy nghĩ về -3
số 3
cần được thêm vào để có số 0 và bạn sẽ thấy số này là 1101
, hãy nhớ rằng phép cộng nhị phân giống như trường tiểu học (số thập phân) chỉ bạn mang theo một khi bạn lên hai chứ không phải 10 .
1101 +
0011 // 3
=
10000
=
0000 // lose carry bit because integers have a constant number of bits.
Vì vậy 1101
được -3
, lật các bit bạn nhận được 0010
mà là hai.
Tôi biết câu trả lời cho câu hỏi này được đăng lại từ lâu, nhưng tôi muốn chia sẻ câu trả lời của mình cho cùng.
Để tìm phần bù của một số, trước tiên hãy tìm tương đương nhị phân của nó. Ở đây, số thập phân 2
được biểu diễn dưới dạng 0000 0010
nhị phân. Bây giờ lấy phần bổ sung của nó bằng cách đảo ngược (lật tất cả 1 thành 0 và tất cả 0 thành 1) tất cả các chữ số của biểu diễn nhị phân của nó, điều này sẽ dẫn đến:
0000 0010 → 1111 1101
Đây là phần bù của một số thập phân 2. Và vì bit đầu tiên, tức là bit dấu là 1 trong số nhị phân, có nghĩa là dấu này âm đối với số được lưu. (ở đây, số được gọi là không 2 mà là phần bù của 2).
Bây giờ, vì các số được lưu dưới dạng phần bù 2 (lấy phần bù của một số cộng với một), do đó, để hiển thị số nhị phân này 1111 1101
, thành số thập phân, trước tiên chúng ta cần tìm phần bù 2 của nó, sẽ là:
1111 1101 → 0000 0010 + 1 → 0000 0011
Đây là phần bổ sung của 2. Biểu diễn thập phân của số nhị phân 0000 0011
, là 3
. Và, vì bit dấu là một như đã đề cập ở trên, vì vậy câu trả lời kết quả là -3
.
Gợi ý: Nếu bạn đọc quy trình này một cách cẩn thận, thì bạn sẽ nhận thấy rằng kết quả cho toán tử bổ sung của một người thực sự là số (toán hạng - trên đó toán tử này được áp dụng) cộng với một dấu có dấu âm. Bạn có thể thử điều này với các số khác quá.
add, flip, add
. 0010
-> 0011
-> 1100
->1101
0010
1101
0010
NOT 0 = 1
và NOT 1 = 0
. Trong hệ thống bốn bit, NOT 0011
(3) = 1100
(12 không dấu, -4 đã ký). Theo những gì tôi hiểu, phần bù của hai được định nghĩa là (NOT n) + 1
và được sử dụng để tìm đối tác âm của một số bất kể số bit. Như vậy , 2c(5) = -5
. Xem, bây giờ nó có ý nghĩa hoàn hảo. Chỉ cần bạn gọi thao tác này là gì: một chút KHÔNG.
int a = 4; System.out.println (~ a); Kết quả sẽ là: -5
'~' của bất kỳ số nguyên nào trong java đại diện cho phần bù 1 của số không. ví dụ tôi đang lấy ~ 4, có nghĩa là trong biểu diễn nhị phân 0100. đầu tiên, độ dài của một số nguyên là bốn byte, tức là 4 * 8 (8 bit cho 1 byte) = 32. Vì vậy, trong bộ nhớ hệ thống 4 được biểu thị là 0000 0000 0000 0000 0000 0000 0000 0100 bây giờ ~ toán tử sẽ thực hiện bổ sung 1 trên nhị phân trên
tức là 1111 1111 1111 1111 1111 1111 1111 1011-> 1 'bổ sung cho bit quan trọng nhất đại diện cho dấu không (hoặc - hoặc +) nếu là 1 thì ký là' - 'nếu là 0 thì ký là' + 'theo kết quả của chúng tôi là một số âm, trong java các số âm được lưu trữ ở dạng bổ sung của 2, kết quả thu được chúng tôi phải chuyển đổi thành phần bù 2 (đầu tiên thực hiện phần bù 1 và chỉ cần thêm phần bù 1). tất cả một số sẽ trở thành số không, ngoại trừ bit 1 có ý nghĩa nhất (là đại diện ký hiệu của chúng tôi cho số đó, có nghĩa là 31 bit 1111 1111 1111 1111 1111 1111 1111 1011 (kết quả thu được của ~ toán tử) 1000 0000 0000 0000 0000 0000 0000 0100 (bổ sung 1)
1000 0000 0000 0000 0000 0000 0000 0101 bây giờ kết quả là -5 hãy xem liên kết này cho video <[Bit toán tử khôn ngoan trong java] https://youtu.be/w4pJ4cGwe9Y
Đơn giản ...........
Khi bổ sung 2 cho bất kỳ số nào, chúng ta có thể tính bằng cách đảo ngược tất cả 1 đến 0 và ngược lại so với chúng ta thêm 1 vào số đó ..
Ở đây N = ~ N tạo ra kết quả - (N + 1) luôn. Bởi vì hệ thống lưu trữ dữ liệu dưới dạng bổ sung 2, có nghĩa là nó lưu trữ ~ N như thế này.
~N = -(~(~N)+1) =-(N+1).
Ví dụ::
N = 10 = 1010
Than ~N = 0101
so ~(~N) = 1010
so ~(~N) +1 = 1011
Bây giờ điểm là từ nơi Minus đến. Ý kiến của tôi là giả sử chúng ta có thanh ghi 32 bit, nghĩa là 2 ^ 31 -1 bit có liên quan đến hoạt động và để nghỉ một bit thay đổi trong tính toán trước đó (bổ sung) được lưu trữ dưới dạng bit dấu thường là 1 bit. Và chúng tôi nhận được kết quả là ~ 10 = -11.
~ (-11) = 10;
Điều trên là đúng nếu printf ("% d", ~ 0); ta được kết quả: -1;
Nhưng printf ("% u", ~ 0) so với kết quả: 4294967295 trên máy 32 bit.
Toán tử bổ sung Bitwise (~) là một đơn vị .
Nó hoạt động theo các phương pháp sau
Đầu tiên, nó chuyển đổi số thập phân đã cho thành nhị phân tương ứng Trong trường hợp 2, trước tiên, nó chuyển đổi 2 thành 0000 0010 (thành số nhị phân 8 bit).
Sau đó, nó chuyển đổi tất cả 1 trong số thành 0 và tất cả các số 0 thành 1, sau đó số sẽ trở thành 1111 1101.
đó là đại diện bổ sung của 2 -3.
Để tìm giá trị không dấu bằng cách sử dụng bổ sung, tức là chỉ cần chuyển đổi 1111 1101 thành thập phân (= 4294967293), chúng ta chỉ cần sử dụng% u trong khi in.
Tôi nghĩ đối với hầu hết mọi người, phần nhầm lẫn xuất phát từ sự khác biệt giữa số thập phân và số nhị phân đã ký, vì vậy hãy làm rõ trước:
đối với thế giới thập phân của con người: 01 có nghĩa là 1, -01 có nghĩa là -1, đối với thế giới nhị phân của máy tính: 101 có nghĩa là 5 nếu không được ký. 101 có nghĩa là (-4 + 1) nếu được ký trong khi chữ số được ký ở vị trí x. | x
vì vậy bit lật của 2 = ~ 2 = ~ (010) = 101 = -4 + 1 = -3 sự nhầm lẫn xuất phát từ việc trộn lẫn kết quả đã ký (101 = -3) và kết quả không mong muốn (101 = 5)
tl; dr ~
lật các bit. Kết quả là dấu hiệu thay đổi. ~2
là số âm ( 0b..101
). Để xuất một số ruby
in âm -
, sau đó bổ sung hai ~2
:-(~~2 + 1) == -(2 + 1) == 3
. Số dương là đầu ra.
Có một giá trị nội bộ và biểu diễn chuỗi của nó. Đối với các số nguyên dương, về cơ bản chúng trùng khớp:
irb(main):001:0> '%i' % 2
=> "2"
irb(main):002:0> 2
=> 2
Cái sau tương đương với:
irb(main):003:0> 2.to_s
"2"
~
lật các bit của giá trị nội bộ. 2
là 0b010
. ~2
là 0b..101
. Hai dấu chấm ( ..
) đại diện cho vô số 1
's. Vì bit có ý nghĩa nhất (MSB) của kết quả là 1
, kết quả là số âm ( (~2).negative? == true
). Để xuất một số ruby
in âm -
, sau đó bổ sung hai giá trị nội bộ. Bổ sung của hai được tính bằng cách lật các bit, sau đó thêm 1
. Bổ sung của hai 0b..101
là 3
. Như vậy:
irb(main):005:0> '%b' % 2
=> "10"
irb(main):006:0> '%b' % ~2
=> "..101"
irb(main):007:0> ~2
=> -3
Để tổng hợp nó, nó lật các bit, làm thay đổi dấu hiệu. Để xuất ra một số âm nó in -
, sau đó ~~2 + 1
( ~~2 == 2
).
Lý do tại sao ruby
xuất ra các số âm như vậy, là vì nó coi giá trị được lưu trữ là phần bù hai của giá trị tuyệt đối. Nói cách khác, những gì được lưu trữ là 0b..101
. Đó là một số âm, và như vậy nó là phần bổ sung của hai giá trị x
. Để tìm x
, nó bổ sung hai 0b..101
. Đó là hai phần bù của hai phần bù của x
. Đó là x
(ví dụ ~(~2 + 1) + 1 == 2
).
Trong trường hợp bạn áp dụng ~
cho một số âm, nó chỉ lật các bit (tuy nhiên thay đổi dấu):
irb(main):008:0> '%b' % -3
=> "..101"
irb(main):009:0> '%b' % ~-3
=> "10"
irb(main):010:0> ~-3
=> 2
Điều khó hiểu hơn là ~0xffffff00 != 0xff
(hoặc bất kỳ giá trị nào khác với MSB bằng 1
). Hãy đơn giản hóa nó một chút : ~0xf0 != 0x0f
. Đó là bởi vì nó được coi 0xf0
là một số dương. Mà thực sự có ý nghĩa. Vì vậy, ~0xf0 == 0x..f0f
. Kết quả là một số âm. Bổ sung của hai 0x..f0f
là 0xf1
. Vì thế:
irb(main):011:0> '%x' % ~0xf0
=> "..f0f"
irb(main):012:0> (~0xf0).to_s(16)
=> "-f1"
Trong trường hợp bạn sẽ không áp dụng toán tử bitwise cho kết quả, bạn có thể xem xét ~
như một -x - 1
toán tử:
irb(main):018:0> -2 - 1
=> -3
irb(main):019:0> --3 - 1
=> 2
Nhưng đó được cho là không sử dụng nhiều.
Một ví dụ Giả sử bạn được cung cấp một mặt nạ mạng 8 bit (để đơn giản) và bạn muốn tính số lượng 0
. Bạn có thể tính toán chúng bằng cách lật các bit và gọi bit_length
( 0x0f.bit_length == 4
). Nhưng ~0xf0 == 0x..f0f
, vì vậy chúng tôi phải cắt bỏ các bit không cần thiết:
irb(main):014:0> '%x' % (~0xf0 & 0xff)
=> "f"
irb(main):015:0> (~0xf0 & 0xff).bit_length
=> 4
Hoặc bạn có thể sử dụng toán tử XOR ( ^
):
irb(main):016:0> i = 0xf0
irb(main):017:0> '%x' % i ^ ((1 << i.bit_length) - 1)
=> "f"
Đầu tiên chúng ta phải chia chữ số đã cho thành chữ số nhị phân của nó và sau đó đảo ngược nó bằng cách thêm vào chữ số nhị phân cuối cùng. Sau khi thực hiện, chúng ta phải đưa ra dấu ngược lại với chữ số trước mà chúng ta đang tìm thấy sự tuân thủ ~ 2 = -3 Giải thích : Dạng nhị phân của 2s là 00000010 thay đổi thành 11111101, đây là dạng bổ sung, sau đó được khen 00000010 + 1 = 00000011 là dạng nhị phân của ba và với -e Ie, -3
Toán tử bit-khôn ngoan là một toán tử đơn nguyên hoạt động theo phương pháp ký hiệu và cường độ theo kinh nghiệm và kiến thức của tôi.
Ví dụ ~ 2 sẽ cho kết quả là -3.
Điều này là do toán tử bit-bit trước tiên sẽ đại diện cho số có dấu và cường độ là 0000 0010 (toán tử 8 bit) trong đó MSB là bit dấu.
Sau đó, nó sẽ lấy số âm 2 là -2.
-2 được biểu thị bằng 1000 0010 (toán tử 8 bit) theo dấu và độ lớn.
Sau đó, nó thêm 1 vào LSB (1000 0010 + 1) cung cấp cho bạn 1000 0011.
Đó là -3.
Javascript dấu ngã (~) ép buộc một giá trị nhất định cho phần bù của một người - tất cả các bit được đảo ngược. Đó là tất cả dấu ngã. Đó không phải là ý kiến. Nó không thêm hay bớt bất kỳ số lượng nào.
0 -> 1
1 -> 0
...in every bit position [0...integer nbr of bits - 1]
Trên các bộ xử lý máy tính để bàn tiêu chuẩn sử dụng các ngôn ngữ cấp cao như JavaScript, số học có chữ ký BASE10 là phổ biến nhất, nhưng hãy nhớ, đây không phải là loại duy nhất. Các bit ở cấp độ CPU có thể được giải thích dựa trên một số yếu tố. Ở cấp độ 'mã', trong trường hợp này là JavaScript, chúng được hiểu là số nguyên có chữ ký 32 bit theo định nghĩa (chúng ta hãy bỏ qua phần nổi này). Hãy coi nó là lượng tử, 32 bit đó đại diện cho nhiều giá trị có thể cùng một lúc. Nó phụ thuộc hoàn toàn vào ống kính chuyển đổi mà bạn xem chúng thông qua.
JavaScript Tilde operation (1's complement)
BASE2 lens
~0001 -> 1110 - end result of ~ bitwise operation
BASE10 Signed lens (typical JS implementation)
~1 -> -2
BASE10 Unsigned lens
~1 -> 14
Tất cả những điều trên là đúng cùng một lúc.