What\'s the easiest way to convert a floating point number to its binary representation in Javascript? (e.g. 1.0 -> 0x3F800000).
I have tried to do it manually, and this
new technologies are making this easy and probably also more forward-compatible. I love extending built in prototypes, not everyone does. So feel free to modify following code to classical procedural approach:
(function() {
function NumberToArrayBuffer() {
// Create 1 entry long Float64 array
return [new Float64Array([this]).buffer];
}
function NumberFromArrayBuffer(buffer) {
// Off course, the buffer must be at least 8 bytes long, otherwise this is a parse error
return new Float64Array(buffer, 0, 1)[0];
}
if(Number.prototype.toArrayBuffer) {
console.warn("Overriding existing Number.prototype.toArrayBuffer - this can mean framework conflict, new WEB API conflict or double inclusion.");
}
Number.prototype.toArrayBuffer = NumberToArrayBuffer;
Number.prototype.fromArrayBuffer = NumberFromArrayBuffer;
// Hide this methods from for-in loops
Object.defineProperty(Number.prototype, "toArrayBuffer", {enumerable: false});
Object.defineProperty(Number.prototype, "fromArrayBuffer", {enumerable: false});
})();
(function() {
function NumberToArrayBuffer() {
// Create 1 entry long Float64 array
return new Float64Array([this.valueOf()]).buffer;
}
function NumberFromArrayBuffer(buffer) {
// Off course, the buffer must be ar least 8 bytes long, otherwise this is a parse error
return new Float64Array(buffer, 0, 1)[0];
}
if(Number.prototype.toArrayBuffer) {
console.warn("Overriding existing Number.prototype.toArrayBuffer - this can mean framework conflict, new WEB API conflict or double inclusion.");
}
Number.prototype.toArrayBuffer = NumberToArrayBuffer;
Number.fromArrayBuffer = NumberFromArrayBuffer;
// Hide this methods from for-in loops
Object.defineProperty(Number.prototype, "toArrayBuffer", {enumerable: false});
Object.defineProperty(Number, "fromArrayBuffer", {enumerable: false});
})();
var test_numbers = [0.00000001, 666666666666, NaN, Infinity, -Infinity,0,-0];
console.log("Conversion symethry test: ");
test_numbers.forEach(
function(num) {
console.log(" ", Number.fromArrayBuffer((num).toArrayBuffer()));
}
);
console.log("Individual bytes of a Number: ",new Uint8Array((666).toArrayBuffer(),0,8));
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
Here's a function that works on everything I've tested it on, except it doesn't distinguish -0.0 and +0.0.
It's based on code from http://jsfromhell.com/classes/binary-parser, but it's specialized for 32-bit floats and returns an integer instead of a string. I also modified it to make it faster and (slightly) more readable.
// Based on code from Jonas Raoni Soares Silva
// http://jsfromhell.com/classes/binary-parser
function encodeFloat(number) {
var n = +number,
status = (n !== n) || n == -Infinity || n == +Infinity ? n : 0,
exp = 0,
len = 281, // 2 * 127 + 1 + 23 + 3,
bin = new Array(len),
signal = (n = status !== 0 ? 0 : n) < 0,
n = Math.abs(n),
intPart = Math.floor(n),
floatPart = n - intPart,
i, lastBit, rounded, j, exponent;
if (status !== 0) {
if (n !== n) {
return 0x7fc00000;
}
if (n === Infinity) {
return 0x7f800000;
}
if (n === -Infinity) {
return 0xff800000
}
}
i = len;
while (i) {
bin[--i] = 0;
}
i = 129;
while (intPart && i) {
bin[--i] = intPart % 2;
intPart = Math.floor(intPart / 2);
}
i = 128;
while (floatPart > 0 && i) {
(bin[++i] = ((floatPart *= 2) >= 1) - 0) && --floatPart;
}
i = -1;
while (++i < len && !bin[i]);
if (bin[(lastBit = 22 + (i = (exp = 128 - i) >= -126 && exp <= 127 ? i + 1 : 128 - (exp = -127))) + 1]) {
if (!(rounded = bin[lastBit])) {
j = lastBit + 2;
while (!rounded && j < len) {
rounded = bin[j++];
}
}
j = lastBit + 1;
while (rounded && --j >= 0) {
(bin[j] = !bin[j] - 0) && (rounded = 0);
}
}
i = i - 2 < 0 ? -1 : i - 3;
while(++i < len && !bin[i]);
(exp = 128 - i) >= -126 && exp <= 127 ? ++i : exp < -126 && (i = 255, exp = -127);
(intPart || status !== 0) && (exp = 128, i = 129, status == -Infinity ? signal = 1 : (status !== status) && (bin[i] = 1));
n = Math.abs(exp + 127);
exponent = 0;
j = 0;
while (j < 8) {
exponent += (n % 2) << j;
n >>= 1;
j++;
}
var mantissa = 0;
n = i + 23;
for (; i < n; i++) {
mantissa = (mantissa << 1) + bin[i];
}
return ((signal ? 0x80000000 : 0) + (exponent << 23) + mantissa) | 0;
}