Bitsel tamamlayıcı operatörü (~ tilde) nasıl çalışır?


Yanıtlar:


283

Negatif sayıların ikisinin pozitif karşılığı tamamlayıcısı olarak saklandığını unutmayın . Örnek olarak, burada ikinin tamamlayıcısında -2'nin temsili: (8 bit)

1111 1110

Bunu elde etmenin yolu, bir sayının ikili temsilini almak, tamamlayıcısını almak (tüm bitleri tersine çevirmek) ve bir sayı eklemektir. İkisi 0000 0010 olarak başlar ve bitleri tersine çevirerek 1111 1101 elde ederiz. Bir tane eklemek bize yukarıdaki sonucu getirir. İlk bit, işaret bitidir, negatif anlamına gelir.

Öyleyse nasıl elde ettiğimize bir bakalım ~ 2 = -3:

İşte yine iki tane:

0000 0010

Sadece tüm bitleri çevirin ve elde ederiz:

1111 1101

Peki, ikisinin tamamlayıcısı -3'e benziyor mu? Pozitif 3: 0000 0011 ile başlayın, tüm bitleri 1111 1100'e çevirin ve negatif değer (-3), 1111 1101 olmak için bir tane ekleyin.

Eğer bitleri 2'de ters çevirirseniz, ikisinin -3'ü tamamlayıcı gösterimini elde edersiniz.

Kompleman operatörü (~) SADECE FLIPS BITS. Bu bitleri yorumlamak makineye kalmıştır.


44
Başka bir şey belki de 1 eklemeden önce flip 1s tamamlayıcı denir olduğunu.
Chris S

3
Birinin Tamamlayıcısı ve İki Tamamlayıcısı'nın farkında olmayan diğerlerine yardımcı olabilir. Bunları burada okuyun. en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement
Sai

1
Bu bitsel DEĞİL operatörü değil mi?
Braden Best

3
Makine, daha yüksek bir pozitif sayı yerine iki tamamlayıcı negatif sayı aldığını nasıl biliyor? İlgili dilin tür sistemi, türün imzalı ve imzasız olduğunu gösteriyor mu?
GL2014

@ GL2014 Sanırım orada kendi sorunuzu cevapladınız. Anladığım kadarıyla, makine ilk etapta çalışmak üzere tasarlandı.
geekidharsh

40

~ değerdeki bitleri çevirir.

Neden ~2olduğu -3sayılar bit düzeyinde temsil edildiği nasıl bir ilgisi vardır. Sayılar ikinin tamamlayıcısı olarak temsil edilir .

Yani, 2 ikili değerdir

00000010

Ve ~ 2 bitleri çevirir, böylece değer şu şekildedir:

11111101

Ki, -3'ün ikili temsilidir.


2
11111101 == ondalık 253 - -3 değil mi?
AKS

10
İşaretli veya işaretsiz bir tamsayıyı temsil edip etmediğine bağlıdır.
driis

Gerçek dünya programlamada kullanımı nedir? Rekabetçi programlamada uygulamaları var mı?
Noah J. Standerson

18

Diğerlerinin de belirttiği gibi ~sadece çevrilmiş bitler (bir sıfıra ve sıfır bire) ve ikisinin tamamlayıcısı kullanıldığından gördüğünüz sonucu elde edersiniz.

Eklenecek bir şey, ikinin tamamlayıcısının neden kullanıldığıdır, bu yüzden negatif sayılardaki işlemler pozitif sayılarla aynı olacaktır. Sıfır elde etmek için eklenecek -3sayı olarak düşünün 3ve bu sayının olduğunu göreceksiniz 1101, ikili eklemenin tıpkı ilkokul (ondalık) toplama gibi olduğunu unutmayın. .

 1101 +
 0011 // 3
    =
10000
    =
 0000 // lose carry bit because integers have a constant number of bits.

Bu nedenle 1101, -3aldığınız bitleri 0010iki olan çevirin .


8

Bu operasyon bir tamamlayıcıdır, bir olumsuzlama değildir.

~ 0 = -1 olduğunu düşünün ve oradan çalışın.

Olumsuzluk için algoritma, "tamamlayıcı, artış" tır.

Biliyor musun? Orada ters sayılar "birin tümleyeni" da olan simetrik, gelir ve hem 0 ve sahip -0.


6

Bu sorunun cevabının uzun bir süre geri gönderildiğini biliyorum, ama aynı cevabımı paylaşmak istedim.

Kişinin bir sayıyı tamamlaması için önce ikili eşdeğerini bulun. Burada, ondalık sayı ikili biçimde 2temsil edilir 0000 0010. Şimdi, ikili temsilinin tüm rakamlarını tersine çevirerek (1'lerin hepsini 0'lara ve 0'ları 1'lere çevirerek) tamamlayıcısını alarak, aşağıdakilerle sonuçlanacaktır:

0000 0010 → 1111 1101

Bu, ondalık sayı 2'nin tamamlayıcısıdır. Ve ilk bit, yani, işaret biti ikili sayıda 1 olduğundan, işaretin depoladığı sayı için negatif olduğu anlamına gelir . (burada, atıfta bulunulan sayı değil 2 değil 2 kişinin tamamlayıcısı).

Şimdi, sayılar 2'nin tamamlayıcısı olarak saklandığından (kişinin bir sayısını artı birini tamamlar), bu yüzden bu ikili sayıyı görüntülemek için, 1111 1101ondalık olarak, önce 2'sinin tamamlayıcısını bulmamız gerekir, bu da:

1111 1101 → 0000 0010 + 1 → 0000 0011

Bu 2'nin tamamlayıcısıdır. İkili sayının ondalık gösterimi 0000 0011,, 3. Ve, işaret biti yukarıda belirtildiği gibi olduğu için, sonuçta ortaya çıkan cevap -3.

İpucu: Bu prosedürü dikkatlice okursanız, kişinin tamamlayıcı operatörünün sonucunun aslında, bu operatörün uygulandığı sayı (işlenen - işlenen) artı bir negatif işaretli olduğunu gözlemlediniz. Bunu diğer numaralarla da deneyebilirsiniz.


Neden iki kez ekliyor? Görüyorum add, flip, add. 0010-> 0011-> 1100->1101
Braden Best

1
Flip, flip, ekle. 1'in tamamlayıcısı için ilk çevir. Ve, sistemde 2'nin tamamlayıcısında saklandığından, sayıyı görüntülemeniz gerektiğinde, 2'nin depolanan sayının tamamlayıcısını gösterecektir (yani ikinci çevirme ve ekleme).
Himanshu Aggarwal

Ama çevirmek (flip (2)) sadece 2 değil mi? 0010 1101 0010
Braden Best

Evet, sadece 2 olacak. Ancak bitler bellekte saklandığında en önemli bit 1 idi, bu da yukarıdaki cevapta açıklandığı gibi sayıyı daha sonra negatif hale getirecektir.
Himanshu Aggarwal

1
Açıkladığınız şeyden ve araştırdığım her şeyden, bu bir ikinin tamamlayıcısı değil, "düzenli" bir tamamlayıcısı veya bitsel olarak DEĞİLDİR. Mantıkta NOT 0 = 1ve NOT 1 = 0. Dört bitlik bir sistemde, NOT 0011(3) = 1100(12 imzasız, -4 imzalı). Anladığım kadarıyla, ikisinin tamamlayıcısı olarak tanımlanır (NOT n) + 1ve bit sayısına bakılmaksızın bir sayının negatif karşılığını bulmak için kullanılır. Böylece 2c(5) = -5,. Bakın, şimdi mantıklı. Bu işlemi çağırdığınız sürece ne olduğu: bir bitwise NOT.
Braden Best

4

int a = 4; System.out.println (~ a); Sonuç: -5

Java'daki herhangi bir tam sayının '~' değeri, 1'in no. örneğin ~ 4 alıyorum, yani ikili gösterimde 0100 anlamına gelir. ilk olarak, bir tamsayının uzunluğu dört bayttır, yani 4 * 8 (1 bayt için 8 bit) = 32. Böylece sistem belleğinde 4, 0000 0000 0000 0000 0000 0000 0000 0000 0100 olarak temsil edilir ~ operatör yukarıdaki ikili nota 1'in tamamlayıcısını gerçekleştirir.

yani 1111 1111 1111 1111 1111 1111 1111 1011-> 1'in tamamlayıcısı, en önemli bit, 1 ise hayır işaretini (ya - ya da +) temsil eder, eğer 0 ise işaret '-' olur, işaret ise '+' Bu bizim sonucumuz negatif bir sayıdır, java'da negatif sayılar 2'nin tamamlayıcı formunda saklanır, elde edilen sonuç 2'nin tamamlayıcısına dönüştürmeliyiz (önce 1'in tamamlayıcısını gerçekleştirin ve sadece 1'e 1 tamamlayıcısını ekleyin). en önemli bit 1 (sayının işaret temsili olan, yani kalan 31 bit 1111 1111 1111 1111 1111 1111 1111 1011 (~ operatörünün elde ettiği sonuç) hariç tümü sıfır olacak) 1000 0000 0000 0000 0000 0000 0000 0000 0100 (1'in tamamlayıcısı)

1 (2'nin tamamlayıcısı)

1000 0000 0000 0000 0000 0000 0000 0000 0000 0101 şimdi sonuç -5 video için bu bağlantıyı kontrol edin <[Java'da bit bilge operatörler] https://youtu.be/w4pJ4cGWe9Y


2

Basitçe ...........

2'nin herhangi bir sayıyı tamamlaması olarak, 1'leri 0'lara ve tersini 1'e ekleyerek hesaplayabiliriz.

Burada N = ~ N sonuçları üretir - (N + 1) her zaman. Çünkü sistem verileri 2'nin tamamlayıcısı biçiminde depolar, yani ~ N bunu depolar.

  ~N = -(~(~N)+1) =-(N+1). 

Örneğin::

  N = 10  = 1010
  Than ~N  = 0101
  so ~(~N) = 1010
  so ~(~N) +1 = 1011 

Şimdi nokta, Eksi'nin geldiği yerdir. Bence 32 bit kayıt var, yani operasyonda 2 ^ 31 -1 bit anlamına gelir ve genellikle 1 olan işaret biti olarak saklanan önceki hesaplamada (tamamlayıcı) değişiklik olan bir bit dinlenmek demektir. Ve sonucu ~ 10 = -11 olarak alıyoruz.

% (-11) = 10;

Yukarıdakiler doğruysa printf ("% d", ~ 0); sonuç alırız: -1;

Ancak printf ("% u", ~ 0) sonuçtan: 329 bit makinede 4294967295.


1

Bitsel tamamlayıcı operatörü (~) tekli bir operatördür.

Aşağıdaki yöntemlere göre çalışır

Önce verilen ondalık sayıyı karşılık gelen ikili değerine dönüştürür. 2 olması durumunda önce 2'yi 0000 0010'a (8 bit ikili sayıya) dönüştürür.

Daha sonra sayıdaki tüm 1'i 0'a ve tüm sıfırları 1'e dönüştürür; sonra sayı 1111 1101 olur.

bu 2'nin -3'ün tamamlayıcı temsilidir.

Tamamlayıcı kullanarak imzasız değeri bulmak için, yani sadece 1111 1101'i ondalığa (= 4294967293) dönüştürmek için, yazdırma sırasında% u kullanabiliriz.


1

Çoğu insan için karışıklık kısmı ondalık sayı ve imzalı ikili sayı arasındaki farktan geliyor, bu yüzden önce açıklığa kavuşalım:

insan ondalık dünyası için: 01 1, -01 -1 anlamına gelir, bilgisayarın ikili dünyası için: 101 imzalanmamışsa 5 anlamına gelir. 101, işaretli rakam x konumundayken imzalanmışsa (-4 + 1) anlamına gelir. | x

2'nin çevrilmiş biti = ~ 2 = ~ (010) = 101 = -4 + 1 = -3 karışıklık, imzalı sonucu (101 = -3) ve izlenmemiş sonucu (101 = 5) karıştırmaktan kaynaklanıyor.


1

tl; dr ~ bitleri çevirir. Sonuç olarak işaret değişir. ~2negatif bir sayıdır ( 0b..101). Çıkış için negatif bir sayı rubybaskılar -ardından, ikinin tamamlayıcısı ~2: -(~~2 + 1) == -(2 + 1) == 3. Pozitif sayılar olduğu gibi verilir.

Bir iç değer ve dize temsili vardır. Pozitif tamsayılar için temel olarak çakışırlar:

irb(main):001:0> '%i' % 2
=> "2"
irb(main):002:0> 2
=> 2

İkincisi şuna eşittir:

irb(main):003:0> 2.to_s
"2"

~dahili değerin bitlerini çevirir. 2olduğunu 0b010. ~2olduğunu 0b..101. İki nokta ( ..) sonsuz sayıda 1' yı temsil eder . Sonucun en önemli biti (MSB) olduğundan sonuç 1negatif bir sayıdır ( (~2).negative? == true). Negatif bir sayı çıktı için rubybaskı -, daha sonra iç değerinin iki tamamlayıcısı. İkinin tamamlayıcısı, bitleri çevirip sonra ekleyerek hesaplanır 1. İkinin tamamlayıcısı 0b..101olduğunu 3. Gibi:

irb(main):005:0> '%b' % 2
=> "10"
irb(main):006:0> '%b' % ~2
=> "..101"
irb(main):007:0> ~2
=> -3

Özetlemek gerekirse, işareti değiştiren bitleri çevirir. Negatif bir sayı çıkarmak için yazdırır -, sonra ~~2 + 1( ~~2 == 2).

Bunun rubygibi negatif sayılar çıkarmanın nedeni, depolanan değeri ikisinin mutlak değeri tamamlayıcısı olarak görmesidir. Başka bir deyişle, depolanan şey 0b..101. Bu negatif bir sayıdır ve bu nedenle ikisinin bir değeri tamamlamasıdır x. Bulmak xiçin, ikisini tamamlar 0b..101. Hangi ikisinin tamamlayıcısı olan ikisinin tamamlayıcısıdır x. Hangisi x(örneğin ~(~2 + 1) + 1 == 2).

~Negatif bir sayıya başvurmanız durumunda , sadece bitleri çevirir (yine de işareti değiştirir):

irb(main):008:0> '%b' % -3
=> "..101"
irb(main):009:0> '%b' % ~-3
=> "10"
irb(main):010:0> ~-3
=> 2

Daha kafa karıştırıcı olan şey ~0xffffff00 != 0xff(veya MSB ile eşit olan başka bir değer 1). Hadi biraz basitleştirmek edelim: ~0xf0 != 0x0f. Çünkü 0xf0pozitif bir sayı gibi davranır . Bu aslında mantıklı. Yani ~0xf0 == 0x..f0f,. Sonuç negatif bir sayıdır. İkinin tamamlayıcısı 0x..f0folduğunu 0xf1. Yani:

irb(main):011:0> '%x' % ~0xf0
=> "..f0f"
irb(main):012:0> (~0xf0).to_s(16)
=> "-f1"

Sonuca bitsel işleçler uygulamazsanız, ~bir -x - 1işleç olarak düşünebilirsiniz :

irb(main):018:0> -2 - 1
=> -3
irb(main):019:0> --3 - 1
=> 2

Ama bu tartışmasız pek bir işe yaramıyor.

Bir örnek Diyelim ki 8 bitlik (basitlik için) bir ağ maskesi verilmiş ve 0's sayısını hesaplamak istiyorsunuz . Bunları bitleri çevirerek bit_length( 0x0f.bit_length == 4) çağırarak hesaplayabilirsiniz . Ancak ~0xf0 == 0x..f0f, gereksiz bitleri kesmemiz gerekiyor:

irb(main):014:0> '%x' % (~0xf0 & 0xff)
=> "f"
irb(main):015:0> (~0xf0 & 0xff).bit_length
=> 4

Veya XOR işlecini ( ^) kullanabilirsiniz:

irb(main):016:0> i = 0xf0
irb(main):017:0> '%x' % i ^ ((1 << i.bit_length) - 1)
=> "f"

0

İlk önce verilen rakamı ikili rakamlara bölmeliyiz ve daha sonra son ikili rakamı ekleyerek tersine çevirmeliyiz. : 2s ikili form 00000010 11111101 değişiklik bu tamamlayıcı olduğunu, daha sonra tamamlandı 00000010 + 1 = 00000011 üç ikili form ve -ign Ie, -3 ile


0

Bit-bilge operatör benim deneyim ve bilgime göre işaret ve büyüklük yöntemi üzerinde çalışan bir tek operatör.

Örneğin ~ 2 -3 ile sonuçlanır.

Bunun nedeni, bit-bilge operatörün öncelikle MSB'nin işaret biti olduğu 0000 0010 (8 bit operatör) olan işaret ve büyüklükteki sayıyı temsil etmesidir.

Daha sonra 2 olan negatif sayıyı -2 alır.

-2, işaret ve büyüklükte 1000 0010 (8 bit operatör) olarak temsil edilir.

Daha sonra LSB'ye (1000 0010 + 1) 1 ekleyerek 1000 0011 verir.

Ki -3.


0

Javascript tilde (~) belirli bir değeri kişinin tamamlayıcısına zorlar - tüm bitler ters çevrilir. Hepsi tilde yapar. Görüşlü bir işaret değil. Herhangi bir miktar katmaz veya çıkarmaz.

0 -> 1
1 -> 0
...in every bit position [0...integer nbr of bits - 1]

JavaScript gibi üst düzey dilleri kullanan standart masaüstü işlemcilerinde, BASE10 imzalı aritmetik en yaygın olanıdır, ancak unutmayın, tek tür değildir. CPU seviyesindeki bitler, bir dizi faktöre dayalı olarak yoruma tabidir. 'Kod' düzeyinde, bu durumda JavaScript, tanım gereği 32 bit işaretli bir tamsayı olarak yorumlanırlar (bunun dışında kayarız). Bunu kuantum olarak düşünün, bu 32 bit bir kerede birçok olası değeri temsil ediyor. Tamamen onları görüntülediğiniz dönüştürücü lense bağlıdır.

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 

Yukarıdakilerin hepsi aynı anda doğrudur.


0

Temelde eylem bir olumsuzlama değil tamamlayıcıdır.

Burada x = ~ x sonuçları üretir - (x + 1) her zaman.

x = ~ 2

- (2 + 1)

-3

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.