17

Possible Duplicate:
What is the “double tilde” (~~) operator in JavaScript?

The D3 tutorial gives a function that produces a random sequence:

var t = 1297110663, // start time (seconds since epoch)
    v = 70, // start value (subscribers)
    data = d3.range(33).map(next); // starting dataset

function next() {
  return {
    time: ++t,
    value: v = ~~Math.max(10, Math.min(90, v + 10 * (Math.random() - .5)))
  };
}

Note the ~~ (tilda tilda) in:

    value: v = ~~Math.max(10, Math.min(90, v + 10 * (Math.random() - .5)))

From playing around in the javascript terminal, I see:

~~1
1
~~-1
-1
~~-1.3
-1
parseInt(5)
5
parseInt(-5)
-5
parseInt(-5.3)
-5
parseInt(5.3)
5

Since ~~ and parseInt seem to be equivalent, whats the rationale for using parseInt?

Community
  • 1
  • 1
Allyl Isocyanate
  • 13,306
  • 17
  • 79
  • 130

4 Answers4

34

They are not equivalent.

  • parseInt() turns strings into numbers, reading up to and ignoring the first non-integer character, and also possibly performing base conversion (e.g. interpreting a string as octal, or hexadecimal).

console.log(



  parseInt(011)           +'\n'+ // 9
  parseInt('011')         +'\n'+ // 11
  parseInt('42 cats')     +'\n'+ // 42
  parseInt('0xcafebabe')  +'\n'+ // 3405691582
  parseInt('deadbeef',16) +'\n'+ // 3735928559
  parseInt('deadbeef',36) +'\n'  // 1049836114599



);
  • var x = ~~y; is a 'trick'—similar to var x = y << 0;—that (ab)uses the unary bitwise NOT operator to force the result to be in the range of a signed 32-bit integer, discarding any non-integer portion.

console.log(



  parseInt(011)                +'\n'+// 9
  parseInt('011')              +'\n'+// 11
  parseInt('42 cats')          +'\n'+// 42
  parseInt('0xcafebabe')       +'\n'+// 3405691582
  parseInt('deadbeef',16)      +'\n'+// 3735928559
  parseInt('deadbeef',36)      +'\n' // 1049836114599



);

Using ~~x is often done because:

  1. It's usually faster than calling a method.
  2. It's faster to type than anything else.
  3. It makes power users feel cool because it's sort of inscrutable and also sort of justifiable. :)

As seen in the cafebabe test, numbers above 231 − 1 (2,147,483,647) or below −231
(−2,147,483,648) will "wrap around" due to the limits of a signed 32-bit integer.

user3840170
  • 26,597
  • 4
  • 30
  • 62
Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • 3
    You might want to explain exactly what `~` is. As in bitwise not. – Endophage May 31 '12 at 21:06
  • why should parseInt('011'); yeld 9? – David Fregoli Feb 24 '13 at 14:42
  • 1
    @DavidFregoli Because of [octal parsing](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/parseInt#Octal_Interpretations_with_No_Radix). – Phrogz Feb 24 '13 at 15:11
  • parseInt('011',8); then? – David Fregoli Feb 24 '13 at 16:40
  • 1
    @DavidFregoli If you are dead-set on using `parseInt` instead of [one of the better choices](http://stackoverflow.com/a/10184402/405017) then you should use `parseInt('011',10)` if you want the result `11`. – Phrogz Feb 24 '13 at 17:13
  • 1
    In modern browsers, that implement ECMAscript 5, there is no octal parsing for strings with leading zero by default, so `parseInt('011');` will return 11 in them. By older browsers like IE8 still return 9, so you have to specify explicit radix to avoid ambiguity. – Ilya Streltsyn Oct 25 '14 at 17:33
9

parseInt isn't limited to signed 32 bit numbers.

   // Top range for a bitwise operator provides a valid result
~~((Math.pow(2,32)/2)-1); // 2147483647

   // Beyond the top range provides undesired result
~~(Math.pow(2,32)/2); // -2147483648

Also, with parseInt you can specify the radix.

  • @gdoron They show that bitwise not clamps to 32-bit values, rolling around into signed-complement land once you hit 2^32 – Phrogz May 31 '12 at 21:11
2
~~"red" === 0

isNaN(parseInt("red"))

parseInt can handle over 32 bit numbers as well

MushinNoShin
  • 4,695
  • 2
  • 32
  • 46
1

Simple: It the more readable and convinient variant.

The bitwise NOT operator is designed for some other use, but can be misused for truncating float values. In your example, Math.floor had also been possible.

Also, they don't behave similiar in many cases. parseInt is no limited to 32 bit, it can parse numbers represented in different positional notations and it also handles non-numeric values with NaN.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375