Javascriptで~~(「ダブルチルド」)は何をしますか?


回答:


248

ビットごとの演算子は暗黙的にオペランドを符号付き32ビット整数に変換するため、小数点以下のすべてを削除します。これは、オペランドが(浮動小数点)数値でも文字列でも機能し、結果は数値になります。

つまり、次の結果が得られます。

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

xが-(2 31)と2 31-1の間にある場合のみ。それ以外の場合、オーバーフローが発生し、数値は「循環」します。

これは、関数の文字列引数を数値に変換するのに役立つと考えられますが、オーバーフローの可能性があることと、非整数での使用が正しくないことの両方のため、「コードゴルフ」以外の方法では使用しません(つまり、読みやすさと堅牢性を犠牲にして、プログラムのソースコードからバイトを無意味にトリミングします)。+xまたはNumber(x)代わりに使用します。


これがNOTのNOTである方法

たとえば、-43.2という数値は次のとおりです。

-43.2 10 = 11111111111111111111111111010101 2

符号付き(2の補数)32ビットの2進数。(JavaScriptは小数点以下を無視します。)ビットを反転すると、次のようになります。

NOT -43 10 = 00000000000000000000000000101010 2 = 42 10

再び反転すると、次のようになります。

NOT 42 10 = 11111111111111111111111111010101 2 = -43 10

これは、Math.floor(-43.2)負の数がゼロから離れずにゼロに丸められるという点で異なります。(floor関数は-44に等しくなりますが、数値が正か負かに関係なく、常に次に低い整数に切り捨てられます。)


6
つまり、切り捨て関数~~を作成するための簡単な方法(そしておそらく良い解決策ですか?)ですが、明らかにjavascript内にあります。
ruffin 2013年

4
JSLintはの使用について不満を言うでしょう~~
リチャードクック

1
Math.trunc()を試す
Xitalogy 2017年

30

最初の〜演算子は、オペランドを整数に強制し(おそらく値を文字列またはブール値に強制した後)、次に最下位の31ビットを反転します。公式にはECMAScriptの数値はすべて浮動小数点ですが、一部の数値はSpiderMonkeyエンジンで31ビット整数として実装されています。

これを使用して、1要素の配列を整数に変換できます。浮動小数点はCの規則に従って変換されます。小数部分の切り捨て。

次に、2番目の〜演算子はビットを反転し、整数になることを知っています。空のオブジェクト{}はtrueと評価され、~~ {}はfalseと評価されるため、これは条件ステートメントで値をブール値に強制することとは異なります。

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

1
ここシャンティのすべての例をありがとう、それは本当に役に立ちました!
シェーントムリンソン

6
また~~undefined // 0
ランプオン2014

1
また~~null // 0
チョビー

技術的には、注文が間違っています。2番目~は、最初の説明~と同じことを行い、その逆も同様です。~オペレータは単項演算子であり、右から左にinterperetedされる~~Xようなもので~(~X)ないような(~~)X(シンタックスエラーされるであろう)
yunzen

20

ECMAScript 6では、同等のもの~~Math.truncです。

小数桁を削除して、数値の整数部を返します。数値は丸められません。

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

ポリフィル:

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

6
やや驚いたことに、~~はMath.trunc、jsperf.com / math-trunc-vs-double-bitwise-not-operatorよりも高速です。ただし、すべてが速度に関するものではありません。読みやすさも。
Gajus 2014

3
~~とMath.truncの間には重要な違いがあります。文字列、NaN、または数値ではないものを渡すと、Math.truncはNaNを返し、~~は常に数値を返します。 0を返します
Buzinas

jsperf.com/math-trunc-vs-double-bitwise-not-operatorによると、Math.truncはChrome 59以降の~~よりもわずかに高速です
Jack Steam

12

する~ようです-(N+1)。したがって~2 == -(2 + 1) == -3、-3でもう一度実行すると、それは元に戻ります~-3 == -(-3 + 1) == 2。おそらく、文字列を単純な方法で数値に変換するだけです。

このスレッドを参照してください:http : //www.sitepoint.com/forums/showthread.php?t=663275

また、より詳細な情報はこちらから入手できます:http : //dreaminginjavascript.wordpress.com/2008/07/04/28/


リンクDrackirをありがとう!
シェーントムリンソン、


4

ほんの少しの警告。ここでの他の答えは私にいくつかの問題を引き起こしました。

その目的は、浮動小数点数の小数点以下を削除することですが、バグの危険を引き起こすいくつかのコーナーケースがあります。~~は避けることをお勧めします。

まず、~~は非常に大きな数では機能しません。

~~1000000000000 == -727279968

別の方法として、Math.trunc()(Gajusが述べたようMath.trunc()に、浮動小数点数の整数部分を返しますが、ECMAScript 6準拠のJavaScriptでのみ使用できます)を使用します。これを行うことで、Math.trunc()ECMAScript-6以外の環境用に独自の環境をいつでも作成できます。

if(!Math.trunc){
    Math.trunc = function(value){
        return Math.sign(value) * Math.floor(Math.abs(value));
    }
}

私は参考のためにこれについてブログ投稿を書きました:http : //bitlords.blogspot.com/2016/08/the-double-tilde-x-technique-in.html



1

文字列を数値に変換する

console.log(~~-1);    // -1
console.log(~~0);     // 0
console.log(~~1);     // 1
console.log(~~"-1");  // -1
console.log(~~"0");   // 0
console.log(~~"1");   // 1
console.log(~~true);  // 1
console.log(~~false); // 0

〜-1は0

if (~someStr.indexOf("a")) {
  // Found it
} else  {
  // Not Found
}

ソース


1

チルダ(〜)にはアルゴリズムがあります-(N + 1)

たとえば:

~0 = -(0+1) = -1
~5 = -(5+1) = -6
~-7 = -(-7+1) = 6

二重チルドは-(-(N + 1)+1)です

例えば:

~~5 = -(-(5+1)+1) = 5
~~-3 = -(-(-3+1)+1) = -3

トリプルチルドは-(-(-(N + 1)+1)+1)

例えば:

~~~2 = -(-(-(2+1)+1)+1) = -3
~~~3 = -(-(-(3+1)+1)+1) = -4
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.