What is the "double tilde" (~~) operator in JavaScript? [duplicate]
Asked Answered
A

4

692

I'm seeing this in some code, and I have no idea what it does:

var jdn = function(y, m, d) {
  var tmp = (m <= 2 ? -1 : 0);
  return ~~((1461 * (y + 4800 + tmp)) / 4) + 
         ~~((367 * (m - 2 - 12 * tmp)) / 12) - 
         ~~((3 * ((y + 4900 + tmp) / 100)) / 4) + 
         d - 2483620;
};

What's the ~~ operator do?

Agnosticism answered 11/5, 2011 at 23:18 Comment(3)
You've probably figured it out by now but it returns the number of days between the millennium and a given dateZhukov
in simple words, it converts '9' into a number 9. And its must faster than Math.floor() even with IE8 if you do the following in console: typeof ~~'9'//numberBluejacket
Math.trunc(), not Math.floor()Acrefoot
B
913

That ~~ is a double Bitwise NOT operator.

It is used as a faster substitute for Math.floor() for positive numbers. It does not return the same result as Math.floor() for negative numbers, as it just chops off the part after the decimal (see other answers for examples of this).

Bordello answered 11/5, 2011 at 23:21 Comment(14)
+1 Was not aware that it floored the value, but I guess it makes sense. (However aren't bitwise operators slower in JavaScript than arithmetic operators making this a slower method?)Banneret
@ghoppe: Worth noting that it differs from .floor() in that it actually just removes anything to the right of the decimal. This makes a difference when used against a negative number. Also, it will always return a number, and will never give you NaN. If it can't be converted to a number, you'll get 0.Snapback
@Banneret - It's probably still faster than Math.floor(), which has to look up the Math global object and do a function call.Agnosticism
The test that the article links to has Math.floor in the title of the text, but Math.round in the code, so that doesn't say anything about the speed of Math.floor...Radiant
@Radiant It's a good thing that test page is editable then. :) I just tested it and ~~ was twice as fast as Math.floor on Safari 5.Bordello
I ran into an integer overflow issue using this technique with very large numbers (the result of dividing numbers from the Navigation Timing API by 62 during base-62 encoding). For instance, in Firefox, Chrome and IE, ~~(2419354838.709677) == -1875612458, whereas Math.floor(2419354838.709677) == 2419354838.Stanton
@JacobWan Yes, this isn't a browser-dependent matter. Bitwise operations in JS produce signed 32-bit integers, so this should be avoided if there's any chance that the input is greater than 2^31 - 1.Foulk
Similar to Math.trunc(), but not Math.floor()Acrefoot
Wrong! It looks like the code example has been through a minifier. It is being used to save space. ~~ is shorter than Math.floor()Mortonmortuary
While ~~ is faster alias of Math.floor(), -~ is an alias of Math.ceil()Dioxide
It looks like for negative numbers you just switch it around: -~ becomes Math.floor() and ~~ becomes Math.ceil(). And here I thought ~~ was just for parsing integer strings...Hammy
~~ is the equivalent of parseIntSpahi
Also to note Math.floor("str") gives NaN while Math.floor('') returns 0 But ~~"str" and ~~"" would return 0Baseball
@JunaidAnwar In my testing on Chromium browsers, ~~ is faster even than Math.trunc().Medicate
R
222

It hides the intention of the code.

It's two single tilde operators, so it does a bitwise complement (bitwise not) twice. The operations take out each other, so the only remaining effect is the conversion that is done before the first operator is applied, i.e. converting the value to an integer number.

Some use it as a faster alternative to Math.floor, but the speed difference is not that dramatic, and in most cases it's just micro optimisation. Unless you have a piece of code that really needs to be optimised, you should use code that descibes what it does instead of code that uses a side effect of a non-operation.

Update 2011-08:

With optimisation of the JavaScript engine in browsers, the performance for operators and functions change. With current browsers, using ~~ instead of Math.floor is somewhat faster in some browsers, and not faster at all in some browsers. If you really need that extra bit of performance, you would need to write different optimised code for each browser.

See: tilde vs floor

Radiant answered 11/5, 2011 at 23:38 Comment(8)
+1 for "it hides the intention of the code", i wasted 10 minutes to know what ~~ does. Anyway I also have to admit it's already strong in me the dark side that's already tempting me to use ~~ in place of Math.floor forever in my new code now on. :))))Nollie
Note that micro tests like JSPerf (necessarily) run the test code enough times that on-the-fly runtime optimizations (such as in V8) kick in. That test shows that (if used very heavily) Math.floor() can be as fast as ~~ on Chrome, but not that it is always the same speed. These days it's just quite hard to say for sure whether or not one bit of code is "faster" than another (accounting for different browsers and invocation scenarios).Ayer
Why on earth is Chrome 22 so much slower than Chrome 8??Epa
@MattSach: The figures are only comparable if tested on the same computer, or if plenty enough people have tested it. Chrome has so many versions that there is rarely more than a handful of persons that has tested the code with each version.Radiant
Just remember that Math.floor() exists for a reason. Don't go off using ~~ because it's 2 microseconds faster than Math.floor if you don't understand where it might cause overflows or other unexpected results.Engaged
This gap has narrowed significantly for Chrome. jsperf.com/math-floor-vs-math-round-vs-parseint/183Marcum
As mentioned in other comments here, it's not the same as Math.floor.Masqat
If anyone is wondering why there is a single operation of converting it to an integer. Here you go #1724075.Gittern
O
174
~(5.5)   // => -6
~(-6)    // => 5
~~5.5    // => 5  (same as Math.trunc(5.5) and Math.floor(5.5))
~~(-5.5) // => -5 (same as Math.trunc(-5.5) but NOT the same as Math.floor(-5.5), which would give -6 )

For more info, see:

Oblation answered 11/5, 2011 at 23:25 Comment(3)
~(-5.5) => 4, ~(4) => -5, ~~(-5.5) => -5. Therefor, not the same as Math.floorPetrology
@zzzzBov, I updated the post to clarify that ~~ is not the same as Math.floor() for negative numbers.Oblation
Math.floor(-5.5), which would give -6. Bcos Math.floor will return largest integer less than or equal to a given number. Math.floor(-5.00000001) also give -6.Reichenberg
S
25

The diffrence is very simple:

Long version

If you want to have better readability, use Math.floor. But if you want to minimize it, use tilde ~~.

There are a lot of sources on the internet saying Math.floor is faster, but sometimes ~~. I would not recommend you think about speed because it is not going to be noticed when running the code. Maybe in tests etc, but no human can see a diffrence here. What would be faster is to use ~~ for a faster load time.

Short version

~~ is shorter/takes less space. Math.floor improves the readability. Sometimes tilde is faster, sometimes Math.floor is faster, but it is not noticeable.

Shanell answered 8/6, 2012 at 8:16 Comment(2)
Right. It's primarily a stylistic choice, like the choice between Boolean(foo), (foo ? true : false), or !!foo when you want to cast a variable to a boolean.Grosz
Math.trunc(), not Math.floor()Acrefoot

© 2022 - 2024 — McMap. All rights reserved.