Javascript

What does double tilde do in Javascript

19 September 2026 · 10 min read

What does  double tilde do in Javascript

If you’re diving into the world of JavaScript, you’ve likely encountered some peculiar operators that might seem cryptic at first glance. One such operator is the double tilde, represented as ~~. What does ~~ (“double tilde”) do in Javascript? It’s not immediately obvious to beginner programmers. This operator, often referred to as the “double NOT bitwise operator,” offers a concise way to perform a specific type of numerical transformation. Many developers use it as a shorthand for certain mathematical operations, but understanding its underlying mechanism is crucial to avoid potential pitfalls. This article explains how the double tilde works, its applications, and when it’s best to use it in your JavaScript code.

Understanding the Bitwise NOT Operator

To fully grasp the functionality of the double tilde operator, it’s essential to understand the bitwise NOT operator (~) upon which it is based. The bitwise NOT operator is a single tilde (~) that performs a bitwise inversion on a number. This means that each bit in the binary representation of the number is flipped: 0 becomes 1, and 1 becomes 0. The bitwise NOT operator returns a 32-bit signed integer. Due to the way signed integers are represented in JavaScript (using two’s complement), applying the bitwise NOT operator effectively returns -(N + 1), where N is the original number. This can be initially confusing, but it’s vital to how the double tilde operates.

For example, let’s take the number 5. Its binary representation (in 32-bit) is 00000000000000000000000000000101. Applying the bitwise NOT operator (~5) flips all the bits, resulting in 11111111111111111111111111111010. This binary number represents -6 in two’s complement. Therefore, ~5 evaluates to -6. This fundamental understanding is critical before exploring the double tilde.

The bitwise NOT operator is not commonly used directly for its bit-flipping capabilities in most JavaScript applications. Its primary significance lies in its role as the foundation for the double tilde operator. Understanding how the single tilde works allows you to predict the outcome when applying it twice, which can simplify certain numerical operations and lead to more concise code.

The Magic of the Double Tilde

So, what happens when you apply the bitwise NOT operator twice (~~)? Applying the bitwise NOT operator twice essentially undoes the initial transformation, but with a crucial caveat. The double tilde operator effectively truncates any decimal portion of a number, converting it to an integer. This is because the bitwise NOT operator only works on integers. When applied to a non-integer, JavaScript implicitly converts it to a 32-bit integer before performing the bitwise operation. This conversion truncates the decimal part.

Here’s how it works step-by-step. First, a number is converted to a 32-bit integer, truncating any decimal portion. Then, the first tilde (~) applies the bitwise NOT operator, resulting in -(N + 1), where N is the truncated integer. The second tilde (~) then applies the bitwise NOT operator again, resulting in -(-N - 1 + 1), which simplifies to N. In essence, ~~x is equivalent to Math.trunc(x) for most practical purposes. However, the double tilde is often perceived as a more concise and performant alternative, though performance differences can vary across JavaScript engines.

The double tilde operator is a shorthand for truncating numbers. This makes it useful in scenarios where you need to ensure a value is an integer, such as when working with array indices or performing calculations that require whole numbers. However, it’s crucial to be aware of its limitations, particularly its behavior with negative numbers and numbers outside the 32-bit integer range. Using the double tilde can improve code readability and potentially offer slight performance gains compared to Math.trunc(), but only if its behavior is thoroughly understood.

Use Cases and Examples

The double tilde operator finds its utility in several practical scenarios. One common use case is truncating floating-point numbers to integers. For example, if you have a value like 3.14159 and you need to use it as an index in an array, you can use ~~3.14159 to get 3. This is much shorter than using Math.floor(3.14159) or parseInt(3.14159).

Another use case is in conjunction with the indexOf method for arrays and strings. The indexOf method returns the index of the first occurrence of a specified value in an array or string, or -1 if the value is not found. Because ~-1 evaluates to 0 (which is falsy), and ~ of any other number is truthy, you can use ~string.indexOf(substring) as a concise way to check if a substring exists within a string. This pattern was particularly prevalent before the introduction of the includes() method, which provides a more readable and explicit way to perform this check. Consider this example:

javascript const str = “Hello, world!”; if (~str.indexOf(“world”)) { console.log(“Substring found!”); }

While the includes() method is generally preferred for its clarity, understanding the double tilde’s use with indexOf is still valuable, especially when encountering older codebases or when aiming for maximum code brevity. Furthermore, the double tilde can be used in performance-critical applications where even small optimizations can make a difference, although the performance gains may be negligible in most cases.

Limitations and Considerations

Despite its utility, the double tilde operator has limitations that developers must be aware of. One significant limitation is its behavior with numbers outside the 32-bit integer range. JavaScript uses 64-bit floating-point numbers for all numeric values, but the bitwise operators, including the tilde, operate on 32-bit integers. This means that if you apply the double tilde to a number outside the range of -2147483648 to 2147483647, the result will be unexpected due to the conversion to a 32-bit integer.

Another consideration is its readability. While the double tilde can make code more concise, it can also make it less understandable, especially for developers who are not familiar with bitwise operators. In such cases, using more explicit methods like Math.trunc() or Math.floor() may be preferable, even if they are slightly longer. According to Douglas Crockford, a renowned JavaScript expert, readability should always be prioritized over brevity, especially in collaborative projects [Crockford on JavaScript].

It’s also important to note that the double tilde operator only truncates towards zero. This means that for positive numbers, it behaves like Math.floor(), but for negative numbers, it behaves like Math.ceil(). This difference can be subtle but crucial in certain applications. Therefore, when choosing between the double tilde and other truncation methods, it’s essential to consider the specific requirements of your code and the potential impact of these subtle differences. Always prioritize clarity and maintainability, especially when working in team environments.

Key Considerations

  • The double tilde only works correctly for numbers within the 32-bit integer range.
  • It truncates towards zero, behaving differently from Math.floor() for negative numbers.
  • Readability should be a primary concern when deciding whether to use the double tilde.

Alternatives to the Double Tilde

While the double tilde offers a concise way to truncate numbers, JavaScript provides several alternative methods that may be more readable or suitable for specific situations. The most direct alternative is Math.trunc(), which explicitly truncates the decimal portion of a number towards zero. This method is generally preferred for its clarity and explicitness, as it clearly communicates the intent of the code. According to a Stack Overflow survey, many developers favor Math.trunc() for its readability [Stack Overflow Discussion].

Another alternative is Math.floor(), which rounds a number down to the nearest integer. This method is suitable when you want to ensure that the result is always an integer less than or equal to the original number. However, it’s important to note that Math.floor() behaves differently from the double tilde for negative numbers. For example, Math.floor(-3.14) returns -4, while ~~(-3.14) returns -3.

Finally, parseInt() can also be used to convert a number to an integer. However, parseInt() has some quirks that can make it less predictable than the other methods. For example, parseInt("42px") returns 42, while the other methods would return NaN. Additionally, parseInt() can interpret numbers as octal or hexadecimal if they start with a leading zero or “0x”, respectively. Therefore, it’s generally recommended to use Math.trunc() or Math.floor() for numerical truncation, unless you specifically need the string parsing capabilities of parseInt().

Alternative Methods

  • Math.trunc(): Explicitly truncates the decimal portion.
  • Math.floor(): Rounds down to the nearest integer.
  • parseInt(): Parses a string and returns an integer.

When to Use (and Not Use) the Double Tilde

Deciding when to use the double tilde depends on a few factors. Use it when you need a concise way to truncate a number to an integer and you are confident that the number will be within the 32-bit integer range. Also, use it when you are working in a performance-sensitive environment where even small optimizations can make a difference, and you have thoroughly tested its behavior.

However, avoid using the double tilde when readability is paramount, especially in collaborative projects. In such cases, prefer Math.trunc() or Math.floor() for their clarity. Also, avoid using it when dealing with numbers that may fall outside the 32-bit integer range, as the results will be unpredictable. Finally, avoid using it if you are unsure about its behavior or if you are working with developers who may not be familiar with bitwise operators. Clarity and maintainability should always be prioritized over brevity, especially in complex or long-lived projects [MDN Web Docs on Bitwise NOT].

In summary, the double tilde is a powerful but potentially obscure operator. Use it judiciously, and always consider the trade-offs between conciseness, performance, and readability. When in doubt, err on the side of clarity, as maintainable code is ultimately more valuable than slightly shorter code.

Infographic illustrating the bitwise operation of the double tilde operator here.
FAQ: Double Tilde in JavaScript -------------------------------
What does the double tilde (~~) operator do in JavaScript?
The double tilde operator (~~) in JavaScript is a shorthand for truncating a number to an integer. It effectively removes the decimal portion of a number by applying the bitwise NOT operator twice.
Is ~~x the same as Math.trunc(x)?
Yes, for most practical purposes, ~~x is equivalent to Math.trunc(x). Both truncate the decimal portion of a number. However, Math.trunc(x) is generally considered more readable.
What are the limitations of the double tilde operator?
The double tilde operator only works correctly for numbers within the 32-bit integer range. It also truncates towards zero, which can behave differently from Math.floor() for negative numbers.
When should I use the double tilde operator?
Use the double tilde operator when you need a concise way to truncate a number to an integer, you are confident that the number **Question & Answer :** I was checking out an online game physics library today and came across the ~~ operator. I know a single ~ is a bitwise NOT, would that make ~~ a NOT of a NOT, which would give back the same value, wouldn't it?

It removes everything after the decimal point because the bitwise operators implicitly convert their operands to signed 32-bit integers. This works whether the operands are (floating-point) numbers or strings, and the result is a number.

In other words, it yields:

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

only if x is between -(231) and 231 - 1. Otherwise, overflow will occur and the number will “wrap around”.

This may be considered useful to convert a function’s string argument to a number, but both because of the possibility of overflow and that it is incorrect for use with non-integers, I would not use it that way except for “code golf” (i.e. pointlessly trimming bytes off the source code of your program at the expense of readability and robustness). I would use +x or Number(x) instead.


How this is the NOT of the NOT

The number -43.2, for example is:

-43.210 = 111111111111111111111111110101012

as a signed (two’s complement) 32-bit binary number. (JavaScript ignores what is after the decimal point.) Inverting the bits gives:

NOT -4310 = 000000000000000000000000001010102 = 4210

Inverting again gives:

NOT 4210 = 111111111111111111111111110101012 = -4310

This differs from Math.floor(-43.2) in that negative numbers are rounded toward zero, not away from it. (The floor function, which would equal -44, always rounds down to the next lower integer, regardless of whether the number is positive or negative.)