Last active
April 16, 2020 18:04
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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