Daniel Baulig, a co-worker at Facebook, told me a little trick related to jDataView function to convert from a uint8 to a int8 in Javascript.

Here's the version I had:

function getInt8() {
  var b = this.getUint8();
  if (b > Math.pow(2, 7) - 1) {
    return b - Math.pow(2, 8);
  }
  return b;
}

Compare it to his version:

< <function getInt8() {
  return this.getUint8() << 24 >> 24;
}

I was really confused because it seems like it's doing a no-op. Here's the full explanation of why the two versions are working.

How it works?

The following table (borrowed from Wikipedia) shows how various 8 bits values are in represented with bits and how they are interpreted in unsigned and signed (using two-complement rule).

Bits uint8 int8
0000 0000 0 0
0000 0001 1 1
0000 0010 2 2
0111 1110 126 126
0111 1111 127 127
1000 0000 128 −128
1000 0001 129 −127
1000 0010 130 −126
1111 1110 254 −2
1111 1111 255 −1

Javascript doesn't natively have a 8 bit integer type, it only has a 32 bits one. When you put a 8 bit integer into a 32 bits one, Javascript is going to fill the remaining bits on the left with zeros as the following table shows.

Bits int32
0000 0000 ... 0000 0000 0
0000 0000 ... 0000 0001 1
0000 0000 ... 0000 0010 2
0000 0000 ... 0111 1110 126
0000 0000 ... 0111 1111 127
0000 0000 ... 1000 0000 128
0000 0000 ... 1000 0001 129
0000 0000 ... 1000 0010 130
0000 0000 ... 1111 1110 254
0000 0000 ... 1111 1111 255

Unfortunately, this doesn't properly handle negative numbers. Because we use two-complement, we've got to fill all the bits with 1 for negative numbers in order to have the same number in a signed 32 bits representation.

Bits int32
0000 0000 ... 0000 0000 0
0000 0000 ... 0000 0001 1
0000 0000 ... 0000 0010 2
0000 0000 ... 0111 1110 126
0000 0000 ... 0111 1111 127
1111 1111 ... 1000 0000 −128
1111 1111 ... 1000 0001 −127
1111 1111 ... 1000 0010 −126
1111 1111 ... 1111 1110 −2
1111 1111 ... 1111 1111 −1

So basically, we've got to fill the 24 remaining bits on the left with the same first bit we have: 0 for positive numbers and 1 for negative numbers.

This is when the trick comes into place. In javascript, there's a binary operator: >> Sign-propagating right shift that moves all the bits to the right and fills the missing bits with the first bit.

So all we have to do is to put our 8 good digits to the far left using << and then use the previous trick to fill the bits with the proper ones 🙂

x x < < 24 (x << 24) >> 24
0000 0000 ... 0000 0000 0000 0000 ... 0000 0000 0000 0000 ... 0000 0000
0000 0000 ... 0000 0001 0000 0001 ... 0000 0000 0000 0000 ... 0000 0001
0000 0000 ... 0000 0010 0000 0010 ... 0000 0000 0000 0000 ... 0000 0010
0000 0000 ... 0111 1110 0111 1110 ... 0000 0000 0000 0000 ... 0111 1110
0000 0000 ... 0111 1111 0111 1111 ... 0000 0000 0000 0000 ... 0111 1111
0000 0000 ... 1000 0000 1000 0000 ... 0000 0000 1111 1111 ... 1000 0000
0000 0000 ... 1000 0001 1000 0001 ... 0000 0000 1111 1111 ... 1000 0001
0000 0000 ... 1000 0010 1000 0010 ... 0000 0000 1111 1111 ... 1000 0010
0000 0000 ... 1111 1110 1111 1110 ... 0000 0000 1111 1111 ... 1111 1110
0000 0000 ... 1111 1111 1111 1111 ... 0000 0000 1111 1111 ... 1111 1111
If you liked this article, you might be interested in my Twitter feed as well.
 
 

Related Posts

  • September 24, 2011 Javascript: Cyclic Object Detection (13)
    URLON.stringify() suffer from a problem, when passed an object that contains a cycle, it will never stop. This article shows 3 techniques in order to detect if an object is cyclical. Edit the object: Mark In order to detect a cycle in an object, the method we learn at school is to […]
  • August 13, 2012 Image Layout Algorithm – Facebook (1)
    Layout Algorithms: Facebook | Google Plus | Lightbox | Lightbox Android | 500px For the redesign of the Photo Section of Facebook we wanted to highlight some photos by making them bigger. It all started with the following mock by Andy Chung: Layout Alternated Blocks My […]
  • February 18, 2013 XSON – Smallest JSON equivalent in XML (4)
    It's often said that XML is very verbose and therefore JSON is better. I wanted to challenge that assumption and find the smallest way to represent any JSON value using XML. table#xson { border-collapse: collapse; margin: 0 auto; } table#xson td, table#xson th { border: 1px solid […]
  • June 8, 2012 CSS – Absolute position taking into account padding (6)
    When looking at the code of Lightbox.com I remarked that they are not using top and left in order to position their images but margin-top and margin-left. I've been wondering why for some time and finally found the reason. It is a way to position absolutely elements in a container and […]
  • September 22, 2011 URLON: URL Object Notation (43)
    #json, #urlon, #rison { width: 100%; font-size: 12px; padding: 5px; height: 18px; color: #560061; } I am in the process of rewriting MMO-Champion Tables and I want a generic way to manage the hash part of the URL (#table__search_results_item=4%3A-slot). I no longer […]