Que fait ~~ («double tilde») en Javascript?


Réponses:


248

Il supprime tout après la virgule car les opérateurs au niveau du bit convertissent implicitement leurs opérandes en entiers 32 bits signés. Cela fonctionne que les opérandes soient des nombres (à virgule flottante) ou des chaînes, et le résultat est un nombre.

En d'autres termes, cela donne:

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

uniquement si x est compris entre - (2 31 ) et 2 31 - 1. Sinon, un débordement se produira et le nombre "passera".

Cela peut être considéré comme utile pour convertir un argument de chaîne de fonction en un nombre, mais à la fois en raison de la possibilité de débordement et du fait qu'il est incorrect pour une utilisation avec des non-entiers, je ne l'utiliserais pas de cette façon, sauf pour "code golf" ( c'est-à-dire réduire inutilement les octets du code source de votre programme au détriment de la lisibilité et de la robustesse). J'utiliserais +xou à la Number(x)place.


Comment c'est le NON du NON

Le nombre -43,2, par exemple, est:

-43,2 10 = 11111111111111111111111111010101 2

sous forme de nombre binaire 32 bits signé (complément à deux). (JavaScript ignore ce qui se trouve après le point décimal.) L'inversion des bits donne:

PAS -43 10 = 00000000000000000000000000101010 2 = 42 10

Inverser à nouveau donne:

PAS 42 10 = 11111111111111111111111111010101 2 = -43 10

Cela diffère du fait Math.floor(-43.2)que les nombres négatifs sont arrondis vers zéro, pas loin de lui. (La fonction de plancher, qui serait égale à -44, arrondit toujours à l'entier inférieur suivant, que le nombre soit positif ou négatif.)


6
Ce qui revient à dire, ~~est un moyen raccourci (et peut-être une bonne solution?) Pour créer une fonction tronquée , mais évidemment en javascript .
ruffin

4
JSLint se plaindra de l'utilisation de ~~.
Richard Cook

1
Essayez Math.trunc ()
Xitalogy

30

Le premier opérateur ~ force l'opérande à un entier (éventuellement après avoir contraint la valeur à une chaîne ou à un booléen), puis inverse les 31 bits les plus bas. Officiellement, les nombres ECMAScript sont à virgule flottante, mais certains nombres sont implémentés sous forme d'entiers 31 bits dans le moteur SpiderMonkey.

Vous pouvez l'utiliser pour transformer un tableau à 1 élément en un entier. Les virgules flottantes sont converties selon la règle C, c'est-à-dire. troncature de la partie fractionnaire.

Le deuxième opérateur ~ inverse ensuite les bits, vous savez donc que vous aurez un entier. Ce n'est pas la même chose que de forcer une valeur à booléenne dans une déclaration de condition, car un objet vide {} est évalué comme vrai, tandis que ~~ {} est évalué comme faux.

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
Merci pour tous les exemples ici Shanti, ça a vraiment aidé!
Shane Tomlinson

6
aussi~~undefined // 0
rampion

1
aussi~~null // 0
chovy

Techniquement, vous avez la mauvaise commande. Le second ~fait ce que vous avez décrit le premier ~et vice versa. L' ~opérateur est un opérateur unaire et est interprété de droite à gauche ~~Xcomme ~(~X)pas comme (~~)X(ce qui serait une erreur de syntaxe)
yunzen

21

Dans ECMAScript 6, l'équivalent de Math.trunc~~ est :

Renvoie la partie intégrante d'un nombre en supprimant tous les chiffres fractionnaires. Il n’arrondit aucun chiffre.

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

Le polyfill:

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

6
De manière assez surprenante, ~~ est plus rapide que Math.trunc, jsperf.com/math-trunc-vs-double-bitwise-not-operator . Cependant, tout n'est pas une question de vitesse; lisibilité aussi.
Gajus

3
Il y a une différence importante entre ~~ et Math.trunc: si vous passez une chaîne, ou NaN ou quelque chose qui n'est pas un nombre, Math.trunc renverra NaN, et ~~ renverra toujours un nombre, dans ces cas, il retournera 0.
Buzinas

Math.trunc est légèrement plus rapide que ~~ dans Chrome 59+, selon jsperf.com/math-trunc-vs-double-bitwise-not-operator .
Jack Steam



4

Juste un petit avertissement. Les autres réponses ici m'ont causé des ennuis.

L'intention est de supprimer quoi que ce soit après la virgule décimale d'un nombre à virgule flottante, mais il a des cas d'angle qui en font un risque de bogue. Je recommanderais d'éviter ~~.

Tout d'abord, ~~ ne fonctionne pas sur de très grands nombres.

~~1000000000000 == -727279968

Comme alternative, utilisez Math.trunc()(comme Gajus l'a mentionné, Math.trunc()renvoie la partie entière d'un nombre à virgule flottante mais n'est disponible qu'en JavaScript conforme à ECMAScript 6). Vous pouvez toujours créer votre propre Math.trunc()environnement non ECMAScript-6 en procédant comme suit:

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

J'ai écrit un article de blog à ce sujet pour référence: http://bitlords.blogspot.com/2016/08/the-double-tilde-x-technique-in.html


1

Voici un exemple de la façon dont cet opérateur peut être utilisé efficacement, où il est logique de l'utiliser:

leftOffset = -(~~$('html').css('padding-left').replace('px', '') + ~~$('body').css('margin-left').replace('px', '')),

La source:

Voir la section Interagir avec les points


1

Conversion de chaînes en nombres

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 est 0

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

la source


1

Tilde (~) a un algorihm - (N + 1)

Par exemple:

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

Le tilde double est - (- (N + 1) +1)

Par exemple:

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

Le tilde triple est - (- (- (N + 1) +1) +1)

Par exemple:

~~~2 = -(-(-(2+1)+1)+1) = -3
~~~3 = -(-(-(3+1)+1)+1) = -4
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.