DEV Community

Asad Memon
Asad Memon

Posted on

40 8

The Mysterious Double Tilde (~~) Operation

Long ago, I was optimizing a hot-path in some game physics code which involved lots of Math.floor() and parseInt() operations. I came across a micro-optimization to cast float or string to int.

~~ operation

console.log(~~1.6); // 1

What's happening?

A single ~ is a unary operator that converts the given number N to -(N+1). For example:

console.log(~2);  // -3
console.log(~1);  // -2
console.log(~0);  // -1

This operation is a bit too specific to be useful to many. But when you apply this operation twice, it's equivalent to Math.floor or parseInt. Examples:

console.log(~~-1);    // -1
console.log(~~0);     // 0
console.log(~~1);     // 1
console.log(~~"-1");  // -1
console.log(~~"0");   // 0
console.log(~~2.4);  // 2
console.log(~~3.9);  // 3
console.log(~~"1");   // 1
console.log(~~true);  // 1
console.log(~~false); // 0

Should I use it in my code?

It depends. As I said, it's a micro-optimization and the performance gains are only significant if you are doing this operation a lot in your code. Do not use it if you care about readability of your code as it might confuse other developers in your team.

Performance comparison

I wrote a little perf-test script to compare.

On Desktop Chrome, Math.floor() is almost as fast as ~~:

On Desktop Safari, ~~ is way faster than both Math.floor() and parseInt():

On iPhone XS, ~~ is also way faster than the others:

Happy Coding!

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (13)

Collapse
 
rohansawant profile image
Rohan Sawant

Damn! I had not idea this was a thing!

Thanks for the great read! 🔥

Collapse
 
asadm profile image
Asad Memon

Thanks!

Collapse
 
savagepixie profile image
SavagePixie

That's a very interesting little thing. Do you happen to have any concrete data (or general idea) as to how much it improves performance?

(I'm not trying to contest your point, I'm just curious)

Collapse
 
asadm profile image
Asad Memon

At the time I first found it, I do remember comparing perf and finding it faster.

I just wrote a quick perf test, see the updated article!

Collapse
 
savagepixie profile image
SavagePixie

Cheers! That is a considerable increase from parseInt indeed!

Collapse
 
havespacesuit profile image
Eric Sundquist

It is a good operator if you want a function that truncates toward zero.

Math.floor(-1.6) // -2
~~-1.6 // -1
Collapse
 
barzi profile image
Andy

Amazing article! Thank you

Collapse
 
stevematdavies profile image
Stephen Matthew Davies

I've been using double tilde ocassionally for a while, but I never knew about the single one!

Collapse
 
georgewl profile image
George WL

I think bitwise operations are always a bad idea.

If someone can't read it and guess what it does, then it shouldn't be used.

Collapse
 
asadm profile image
Asad Memon • Edited

You are right. It depends, as I said.

I used it because of perf gains I needed. Maybe a comment explaining the code line would be a good compromise for situations like this.

Collapse
 
lucashogie profile image
Lucas H.

Super interesting! Thank you for the read!

Collapse
 
iam10k profile image
Tyler Encke • Edited

On Firefox, Math.floor is actually faster by 23%.

Firefox Results

Collapse
 
orashus profile image
Rash Edmund Jr

woah,
i'm down for using this.
besides, it's obviously faster.

thank you for this.

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more