12 votes

The Mysterious Double Tilde (~~) Operation

6 comments

  1. [2]
    Macil
    Link
    Similarly, !! is sometimes used to cast something to a boolean. (! is NOT for booleans, ~ is NOT for 32-bit ints.) Note that ~~ isn't exactly equivalent to Math.floor: ~ casts a value to a 32-bit...

    Similarly, !! is sometimes used to cast something to a boolean. (! is NOT for booleans, ~ is NOT for 32-bit ints.)

    Note that ~~ isn't exactly equivalent to Math.floor: ~ casts a value to a 32-bit int specifically. Any value that doesn't fit inside the 32-bit int range (-2^31 to 2^31-1) will have its upper-bits stripped off by any 32-bit operations, but Math.floor will work on them fine.

    A popular alternative to ~~x you may see around in codebases is x|0, which accomplishes the same thing (casts the value to a 32-bit int).

    7 votes
    1. musa_totter
      Link Parent
      IIRC things like x = x|0 are the idiomatic way to declare that a variable or parameter is an int in asm.js, so that may be another reason this may pop up. (Though asm.js has been left by the...

      IIRC things like x = x|0 are the idiomatic way to declare that a variable or parameter is an int in asm.js, so that may be another reason this may pop up. (Though asm.js has been left by the wayside in favor of webassembly IIRC)

      1 vote
  2. [4]
    wakamex
    Link
    when two tildes are better than one. is this a thing in any other programming languages?

    when two tildes are better than one. is this a thing in any other programming languages?

    1 vote
    1. [3]
      musa_totter
      Link Parent
      According to my understanding, this is logically equivalent to a type cast, like so (C++): #include <iostream> int main(int argc, char *argv[]) { std::cout << (int)3.7 << std::endl; return 0; }...

      According to my understanding, this is logically equivalent to a type cast, like so (C++):

      #include <iostream>
      
      int main(int argc, char *argv[]) {
          std::cout << (int)3.7 << std::endl;
      
          return 0;
      }
      

      This prints 3. But since it seems there is no built-in casting mechanism in Javascript, tricks like this arise to force the cast to happen. Checkout out a benchmark of this and similar methods on your browser here. On my browser, this trick is equally as fast as bitwise-or and bitshifting.

      5 votes
      1. [2]
        unknown user
        Link Parent
        There are ways to parse a value is a float and as an integer in JS. Number.parseInt(3.75) === 3 Number.parseFloat(3 + 0.14) === 3.14

        There are ways to parse a value is a float and as an integer in JS.

        Number.parseInt(3.75) === 3

        Number.parseFloat(3 + 0.14) === 3.14

        1. musa_totter
          Link Parent
          That is true, but these appear to be different somehow from type casts, because they are slower than implicit casts, according to benchmarks. After a little investigating, it would seem that...

          That is true, but these appear to be different somehow from type casts, because they are slower than implicit casts, according to benchmarks.

          After a little investigating, it would seem that parseInt actually converts its first argument to string before parsing, which not only slows it down, but also means that its result will sometimes be incorrect. For example, parseInt(6.022e23) returns 6, whereas the correct answer would be 602200000000000000000000.

          3 votes