Take me back!

Bits and Bytes for the Javascripter

Slightly simplified for the sake of... well, simplicity

Nowadays, many programmers don't ever expect to think about bits and bytes. After all, bits are the most basic unit of how computers store and communicate information. High level languages like Javascript and Python often manage the size of data types for the programmer, and abstract many lower level concepts. So, in most cases those programmers would be right; there is really no need to ever think about bits and the other icky low level stuffs.

However, there are some situations where programmers would need to know at least a little about these topics, such as reading a file in bytes or working with cryptography.


So, the Basics

A bit is, apparently, a combination of the words "binary digit". Binary of course means only two states, so of course a bit has two states, 0 and 1.

8 bits make a byte, and since each bit has two possible states (0 or 1), that means 1 byte has 256 (2^8) states. Yes, that is why you see the numbers 255 or 256 used all the time.

Bytes can be represented in several different ways.


Doing in Javascript

For Javascript, bytes are typically represented by an Uint8Array, where each number (Uint8, so from 0-255) in the array represents one byte.

Here are some examples of how to work with these Uint8Arrays, as well as some utility functions.


Useful utility functions:

function decimal_to_bits(decimal) {
  let binary_string = "";
  while (true) {
    if (decimal === 0) {
      break;
    }
    binary_string += String(decimal % 2);
    decimal = Math.floor(decimal / 2);
  }
  //reverses
  return binary_string.split("").reverse().join("");
}

//an even simpler version of the above
function decimal_to_bits_simple(decimal) {
  return decimal.toString(2);
}

function bits_to_decimal(bits) {
  return parseInt(bits, 2);
}

//like `decimal_to_bits`, but ensures bits returned is 8
function decimal_to_byte(decimal) {
  if (decimal > 255) return;
  let binary_string = "";
  while (true) {
    if (decimal === 0) {
      break;
    }
    binary_string += String(decimal % 2);
    decimal = Math.floor(decimal / 2);
  }
  //pad if not one byte long
  if (binary_string.length !== 8) {
    binary_string = binary_string+"0".repeat(8 - binary_string.length);
  }
  //reverse binary array
  return binary_string.split("").reverse();
}

function hex_to_decimal(hex_string) {
  return parseInt(hex_string, 16);
}

To hexadecimal:

function uint8_to_hex(uint8) {
  let hex_string = "";
  for (let i=0; i < uint8.length; i++) {
    let hex = uint8[i].toString(16);
    //if hex is one character long, that means it is 4 bits (1/2 byte)
    //so, pad it with 0, so that the hex string is 8 bits (1 byte)
    //this ensures the returned hex string is the same amount of bytes as the uint8 array provided
    if (hex.length === 1) {
      hex = "0" + hex;
    }
    hex_string += hex;
  }
  return hex_string;
}

To decimal:

function uint_to_decimal(uint8) {
  //convert uint8array into binary
  let binary_string = "";
  for (let i=0; i < uint8.length; i++) {
    binary_string += decimal_to_byte(uint8[i]);
  }
  //then convert binary into decimal
  return bits_to_decimal(binary_string);
}

Random bytes:

Note: Especially when dealing with cryptography, it is very important to use a secure source of randomness. Especially NOT use: Math.random or timestamps or unchanging seeds.
function random_bytes(bytes_num) {
  //this may not work in older browsers
  let uint8 = new Uint8Array(bytes_num);
  window.crypto.getRandomValues(uint8);
  return uint8;
}

Please let me know if you need further help, questions, or found a mistake in the code in my Discord Server.