7

I found a code from here that converts Javascript number to inner IEEE representation as two Uint32 values:

function DoubleToIEEE(f)
{
  var buf = new ArrayBuffer(8);
  (new Float64Array(buf))[0] = f;
  return [ (new Uint32Array(buf))[0] ,(new Uint32Array(buf))[1] ];
}

How to convert the returned value back to Javascript number? This way:

var number = -10.3245535;
var ieee = DoubleToIEEE(number)
var number_again = IEEEtoDouble(ieee);
// number and number_again should be the same (if ever possible)
Community
  • 1
  • 1
Timo Kähkönen
  • 11,962
  • 9
  • 71
  • 112
  • Does this answer your question? [Read/Write bytes of float in JS](https://stackoverflow.com/questions/4414077/read-write-bytes-of-float-in-js) – user202729 Jan 30 '21 at 10:45

2 Answers2

8

I found a possible solution, which seems to work:

function IEEEToDouble(f)
{
  var buffer = new ArrayBuffer(8);
  (new Uint32Array(buffer))[0] = f[0];
  (new Uint32Array(buffer))[1] = f[1];
  return new Float64Array(buffer)[0];
}

Usage:

var a = DoubleToIEEE(-0.1234);
console.log(a); // [0, 3220176896]
var b = IEEEToDouble(a);
console.log(b); // -0.1234
Timo Kähkönen
  • 11,962
  • 9
  • 71
  • 112
  • 1
    If anyone looking to convert from binary representation string: `const BinaryStringToDouble = (x) => IEEEToDouble([x.substring(32), x.substring(0, 32)].map(p => parseInt(p, 2)));` – AgainPsychoX Dec 06 '21 at 18:37
  • beware of byte order; use DataView – Jason S Jan 24 '23 at 04:48
7

That code is ugly as hell. Use

function DoubleToIEEE(f) {
  var buf = new ArrayBuffer(8);
  var float = new Float64Array(buf);
  var uint = new Uint32Array(buf);
  float[0] = f;
  return uint;
}

If you want an actual Array instead of a Uint32Array (shouldn't make a difference in the most cases), add an Array.from call. You can also reduce this to a oneliner by passing the value to the Float64Array constructor:

function DoubleToIEEE(f) {
  // use either
  return new Uint32Array(Float64Array.of(f).buffer);
  return Array.from(new Uint32Array(Float64Array.of(f).buffer));
  return Array.from(new Uint32Array((new Float64Array([f])).buffer));
}

The inverse would just write the inputs into the uint slots and return the float[0] value:

function IEEEToDouble(is) {
  var buf = new ArrayBuffer(8);
  var float = new Float64Array(buf);
  var uint = new Uint32Array(buf);
  uint[0] = is[0];
  uint[1] = is[1];
  return float[0];
}

which can be shortened to

function IEEEToDouble(is) {
  return (new Float64Array(Uint32Array.from(is).buffer))[0];
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Could you kindly explain to us dummies why the code is ugly? – Timo Kähkönen Mar 29 '17 at 11:03
  • @TimoKähkönen The assignment to the throwaway-typedarray on the left hand side is confusing, it's better to write it out explicitly with a variable. And the two `Uint32Array`s where one would suffice seem inefficient. All that makes it hard to understand the data flow and find the inverse function. And of course, I prefer the single-expression forms :-) – Bergi Mar 29 '17 at 16:31
  • Thanks for the explanation. I accepted your answer. – Timo Kähkönen Mar 29 '17 at 22:43
  • which version of Javascript/ECMAscript does this require? – Jason S May 05 '17 at 20:07
  • @JasonS ES6, though typed arrays can be polyfilled and were supported in some browsers earlier than ES6 as well IIRC. – Bergi May 06 '17 at 10:09