Javascript'te ~~ ("çift tilde") ne işe yarar?


Bugün bir çevrimiçi oyun fizik kütüphanesini inceliyordum ve ~~ operatörüne rastladım. Tek bir ~ bit düzeyinde NOT olduğunu biliyorum, bu durumda ~~ bir NOT'un NOT'u olur ve aynı değeri geri verir, değil mi?

Cevap #1

Ondalık noktadan sonraki her şeyi kaldırır çünkü bit düzeyinde operatörler, işlenen değerlerini zımni olarak işaretli 32-bit tamsayılara dönüştürür. Bu, işlenen değerler (ondalıklı) sayılar veya stringler olsun çalışır ve sonuç bir sayıdır.

Başka bir deyişle, şu sonucu verir:

function(x) {
  if(x < 0) return Math.ceil(x);
  else return Math.floor(x);
}

sadece x -(231) ile 231 - 1 arasında ise. Aksi takdirde, taşma meydana gelir ve sayı "dönerek" değer kaybeder.

Bu, bir fonksiyonun string argümanını sayıya dönüştürmek için faydalı olarak değerlendirilebilir, ancak taşma olasılığı ve tam sayı olmayan değerlerle kullanıma uygun olmaması nedeniyle, bunu yalnızca "code golf" (yani okunabilirlik ve sağlamlıktan ödün vererek programınızın kaynak kodundaki baytları gereksiz yere kısaltmak) dışında bir şekilde kullanmazdım. Bunun yerine +x veya Number(x) kullanırdım.

Bunun, DEĞİL'in DEĞİL'i nasıl olduğu

Örneğin -43.2 sayısı şudur:

-43,210=111111111111111111111111110101012

imzalı (iki tamamlayıcı) 32-bit ikili sayı olarak. (JavaScript ondalık noktadan sonrasını görmezden gelir.) Bitleri tersine çevirmek şunu verir:

NOT -4310=000000000000000000000000001010102=4210

Tekrar ters çevirmek şunu verir:

NOT 4210=111111111111111111111111110101012=-4310

Bu, Math.floor(-43.2)'den farklıdır çünkü negatif sayılar sıfıra doğru yuvarlanır, ondan uzağa değil. (Floor fonksiyonu, ki bu -44 eder, sayı pozitif veya negatif olsun her zaman bir sonraki daha düşük tam sayıya aşağı yuvarlar.)

Cevap #2

İlk ~ operatörü, işleci bir tam sayıya zorlar (değeri bir string veya boolean’a zorladıktan sonra olabilir) ve ardından en düşük 31 biti tersine çevirir. Resmî olarak ECMAScript sayıların hepsi kayan nokta sayısıdır, ancak bazı sayılar SpiderMonkey motorunda 31-bit tam sayı olarak uygulanır.

Bunu, tek elemanlı bir diziyi bir tam sayıya dönüştürmek için kullanabilirsiniz. Ondalıklı sayılar C kuralına göre dönüştürülür, yani kesirli kısmın törpülenmesiyle.

İkinci ~ operatörü ise bitleri tekrar tersine çevirir, böylece bir tamsayıya sahip olacağınızı bilirsiniz. Bu, bir değeri koşul ifadesinde boolean'a zorlamakla aynı şey değildir, çünkü boş bir nesne {} true olarak değerlendirirken, ~~{} false olarak değerlendirilir.

js>~~"yes"
0
js>~~3
3
js>~~"yes"
0
js>~~false
0
js>~~""
0
js>~~true
1
js>~~"3"
3
js>~~{}
0
js>~~{a:2}
0
js>~~[2]
2
js>~~[2,3]
0
js>~~{toString: function() {return 4}}
4
js>~~NaN
0
js>~~[4.5]
4
js>~~5.6
5
js>~~-5.6
-5

Cevap #3

ECMAScript 6'da, ~~'nin karşılığı Math.trunc'dur:

Bir sayının kesirli basamaklarını çıkararak tam kısmını döndürür. Hiçbir sayıyı yuvarlamaz.

Math.trunc(13.37)   // 13
Math.trunc(42.84)   // 42
Math.trunc(0.123)   //  0
Math.trunc(-0.123)  // -0
Math.trunc("-1.123")// -1
Math.trunc(NaN)     // NaN
Math.trunc("foo")   // NaN
Math.trunc()        // NaN

Polyfill:

function trunc(x) {
    return x < 0 ? Math.ceil(x) : Math.floor(x);
}

Cevap #4

~ gözüken şey -(N+1) işlemini yapıyor gibi görünüyor. Yani ~2 == -(2 + 1) == -3. Eğer bunu -3 üzerinde tekrar yaparsan, geri döner: ~-3 == -(-3 + 1) == 2. Muhtemelen sadece bir stringi dolambaçlı bir yolla sayıya çeviriyor.

Bu konuyu inceleyin: https://www.sitepoint.com/community/t/double-tilde/51608

Ayrıca, daha ayrıntılı bilgiler burada mevcuttur: https://dreaminginjavascript.wordpress.com/2008/07/04/28/

Cevap #5

Verilen ~N, -(N+1) olduğuna göre, ~~N ise -(-(N+1) + 1) olur. Bu da, açıkça, hoş bir numaraya yol açar.

İlgili makaleler