Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a floating point number to its binary representation (IEEE 754) in Javascript?

Tags:

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 works to some extent (with usual numbers), but it fails for very big or very small numbers (no range checking) and for special cases (NaN, infinity, etc.):

function floatToNumber(flt) {     var sign = (flt < 0) ? 1 : 0;     flt = Math.abs(flt);     var exponent = Math.floor(Math.log(flt) / Math.LN2);     var mantissa = flt / Math.pow(2, exponent);      return (sign << 31) | ((exponent + 127) << 23) | ((mantissa * Math.pow(2, 23)) & 0x7FFFFF); } 

Am I reinventing the wheel?

EDIT: I've improved my version, now it handles special cases.

function assembleFloat(sign, exponent, mantissa) {     return (sign << 31) | (exponent << 23) | (mantissa); }  function floatToNumber(flt) {     if (isNaN(flt)) // Special case: NaN         return assembleFloat(0, 0xFF, 0x1337); // Mantissa is nonzero for NaN      var sign = (flt < 0) ? 1 : 0;     flt = Math.abs(flt);     if (flt == 0.0) // Special case: +-0         return assembleFloat(sign, 0, 0);      var exponent = Math.floor(Math.log(flt) / Math.LN2);     if (exponent > 127 || exponent < -126) // Special case: +-Infinity (and huge numbers)         return assembleFloat(sign, 0xFF, 0); // Mantissa is zero for +-Infinity      var mantissa = flt / Math.pow(2, exponent);     return assembleFloat(sign, exponent + 127, (mantissa * Math.pow(2, 23)) & 0x7FFFFF); } 

I'm still not sure if this works 100% correctly, but it seems to work good enough. (I'm still looking for existing implementations).

like image 804
GameZelda Avatar asked Jun 22 '10 19:06

GameZelda


People also ask

Does JavaScript use IEEE 754?

The JavaScript Number type is a double-precision 64-bit binary format IEEE 754 value, like double in Java or C#. This means it can represent fractional values, but there are some limits to what it can store.

How do you represent a floating point number in binary?

The sign of a binary floating-point number is represented by a single bit. A 1 bit indicates a negative number, and a 0 bit indicates a positive number. Before a floating-point binary number can be stored correctly, its mantissa must be normalized.

How do you represent a floating point number in JavaScript?

The representation of floating points in JavaScript follows the IEEE-754 format. It is a double precision format where 64 bits are allocated for every floating point.


1 Answers

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}); })(); 

Test:

(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>
like image 94
Tomáš Zato - Reinstate Monica Avatar answered Oct 22 '22 16:10

Tomáš Zato - Reinstate Monica