Skip to content

Instantly share code, notes, and snippets.

@andria-dev
Last active April 16, 2020 18:04
Show Gist options
  • Save andria-dev/56350a9ce1095e36759074364add192e to your computer and use it in GitHub Desktop.
Save andria-dev/56350a9ce1095e36759074364add192e to your computer and use it in GitHub Desktop.
A function for converting a floating point number into binary (half precision)
// Half Precision Floats
/**
* @description Converts a binary number like: 1100101011000000
* sign | exponent | significand
* 1 | 10010 | 1011000000
*
* back into it's decimal representation, in this case it's -13.5
*
* @param {string} binaryString a binary number in string format
* @returns {number} the decimal floating point representation of `binaryString`
*/
function binaryToDecimal(binaryString) {
const sign = binaryString[0] === '1' ? -1 : 1;
binaryString = binaryString.slice(1);
const exponent = parseInt(binaryString.slice(0, 5), 2);
const N = exponent - 15;
const significand = binaryString.slice(5);
let binary;
if (N > 0) {
binary = `1${significand.slice(0, N)}.${significand.slice(N)}`;
} else if (N < 0) {
binary = `${'0'.repeat(N * -1 - 1)}.1${significand}`;
} else {
binary = `1.${significand}`;
}
let result = 0;
const [left, right] = binary.split('.');
for (let index = 0; index < left.length; ++index) {
const digit = parseInt(left[left.length - index - 1], 2);
result += digit * 2 ** index;
}
for (let index = 0; index < right.length; ++index) {
const digit = parseInt(right[index]);
result += digit * 2 ** -(index + 1);
}
return result * sign;
}
/**
* @description Takes a number such as -13.5 and converts it into a Half Precision Floating-Point binary string
* by first converting it into a binary number (-1101.1) and then calculating the sign, exponent,
* and significand from that.
*
* sign | exponent | significand
* 1 | 10010 | 1011000000
*
* @param {number} decimal a floating point decimal number
* @returns {string} a string of the IEEE-754 Half Precision Floating-Point binary representation of `decimal`
*/
function decimalToBinary(decimal) {
let binary = decimal.toString(2);
const sign = binary[0] === '-' ? '1' : '0';
if (sign === '1') {
binary = binary.slice(1);
}
// find most significant 1 and move decimal point to after it
let normalized = '';
let hasJesusBit = false;
const decimalPointIndex = { old: null, new: null };
for (let index = 0; index < binary.length; ++index) {
const current = binary[index];
if (current === '.') {
decimalPointIndex.old = index;
continue;
}
if (hasJesusBit) {
normalized += current;
} else if (current === '1') {
decimalPointIndex.new = index;
if (decimalPointIndex.old === null) {
decimalPointIndex.new += 1;
}
normalized += current + '.';
hasJesusBit = true;
}
}
const significand = normalized.slice(2);
console.log(decimalPointIndex);
const N = decimalPointIndex.old - decimalPointIndex.new;
const exponent = (15 + N).toString(2).padStart(5, '0');
return sign + exponent + significand.padEnd(10, '0');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment