29

I am trying to perform something that is brain-dead simple in any other language but not javascript: get the bits out of float (and the other way around).

In C/C++ it would be something like

float a = 3.1415;
int b = *((int*)&a);

and vise-versa

int a = 1000;
float b = *((float*)&a);

In C# you can use the BitConverter ...floatBits or something alike in Java... Even in VB6 for Christ's sake you can memcpy a float32 into an int32. How on earth can I translate between and int and a float in javascript?

Stelios
  • 293
  • 1
  • 3
  • 5
  • 2
    Hey, just wanted to say thanks for answering my question in asking yours. I needed to know how to do flaot/int conversions in C++; – LaikaN57 Oct 09 '10 at 21:26
  • Remark: casting pointers like this violates strict aliasing rule in C++. You have to use a memcpy. – user202729 Jan 30 '21 at 02:03
  • 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:42

5 Answers5

34
function DoubleToIEEE(f)
{
    var buf = new ArrayBuffer(8);
    (new Float64Array(buf))[0] = f;
    return [ (new Uint32Array(buf))[0] ,(new Uint32Array(buf))[1] ];
}
bensiu
  • 24,660
  • 56
  • 77
  • 117
passing korean
  • 341
  • 1
  • 3
  • 2
  • 5
    And to the other direction (from bytes to floats), see: http://stackoverflow.com/a/21282715/1691517. – Timo Kähkönen Jan 22 '14 at 12:19
  • 1
    If anyone looking for converting to binary representation string: `const DoubleToBinaryString = (x) => DoubleToIEEE(x).reverse().map(p => p.toString(2).padStart(32, '0')).join('');` – AgainPsychoX Dec 06 '21 at 18:36
8

You certainly don't get anything low-level like that in JavaScript. It would be extremely dangerous to allow recasting and pointer-frobbing in a language that has to be safe for untrusted potential-attacker web sites to use.

If you want to get a 32-bit IEEE754 representation of a single-precision value in a Number (which remember is not an int either; the only number type you get in JavaScript is double), you will have to make it yourself by fiddling the sign, exponent and mantissa bits together. There's example code here.

bobince
  • 528,062
  • 107
  • 651
  • 834
  • Just took a look at the Javascript in the babbage.cs.qc.edu site -- It may produce correct answers, and may work well on the online calculator, but it's horribly written & not suitable for reuse in my opinion. – Jason S Mar 17 '11 at 17:54
  • 15
    I fail to see why adding native IEEE binary format conversion to/from a JavaScript number would be a security issue. There's no recasting or pointers involved in this matter. – akauppi Apr 01 '12 at 13:06
  • @akauppi there is no security issue. No more than allowing contiguous memory ownership with Uint8Array, Uint16Array, so on. Just gotta have a Float32 object and give it a native method toUint8Array. It will be more efficient than the alternatives available today. Since all numbers in javascript are analogous to doubles wrapped in a variant, the cost of doing this would basically be creating a uint8array variant of Number's internal representations bytes, and memcpy that number of bytes from the number's internal to the uint8array's internal memory. – Dmytro Jul 18 '17 at 17:04
  • 8
    The link seems to be broken. Maybe you want to add the example code into the answer? (From [Help Center > Answering > How do I write a good answer?](https://stackoverflow.com/help/how-to-answer): "Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.") – T S Jul 07 '18 at 20:14
4
function FloatToIEEE(f)
{
    var buf = new ArrayBuffer(4);
    (new Float32Array(buf))[0] = f;
    return (new Uint32Array(buf))[0];
}

Unfortunately, this doesn't work with doubles and in old browsers.

Triang3l
  • 1,230
  • 9
  • 29
3
  1. JavaScript uses double (IEEE 754) to represent all numbers
  2. double consists of [sign, exponent(11bit), mantissa(52bit)] fields. Value of number is computed using formula (-1)^sign * (1.mantissa) * 2^(exponent - 1023). (1.mantissa - means that we take bits of mantissa add 1 at the beginning and tread that value as number, e.g. if mantissa = 101 we get number 1.101 (bin) = 1 + 1/2 + 1/8 (dec) = 1.625 (dec).
  3. We can get value of sign bit testing if number is greater than zero. There is a small issue with 0 here because double have +0 and -0 values, but we can distinguish these two by computing 1/value and checking if value is +Inf or -Inf.
  4. Since 1 <= 1.mantissa < 2 we can get value of exponent using Math.log2 e.g. Math.floor(Math.log2(666.0)) = 9 so exponent is exponent - 1023 = 9 and exponent = 1032, which in binary is (1032).toString(2) = "10000001000"
  5. After we get exponent we can scale number to zero exponent without changing mantissa, value = value / Math.pow(2, Math.floor(Math.log2(666.0))), now value represents number (-1)^sign * (1.mantissa). If we ignore sign and multiply that by 2^52 we get integer value that have same bits as 1.mantissa: ((666 / Math.pow(2, Math.floor(Math.log2(666)))) * Math.pow(2, 52)).toString(2) = "10100110100000000000000000000000000000000000000000000" (we must ignore leading 1).
  6. After some string concat's you will get what you want

This is only proof of concept, we didn't discuss denormalized numbers or special values such as NaN - but I think it can be expanded to account for these cases too.

@bensiu answers is fine, but if find yourself using some old JS interpreter you can use this approach.

csharpfolk
  • 4,124
  • 25
  • 31
-3

Like the other posters have said, JavaScript is loose typed, so there is no differentiation in data types from float to int or vice versa.

However, what you're looking for is

float to int:

Math.floor( 3.9 ); // result: 3 (truncate everything past .) or
Math.round( 3.9 ); // result: 4 (round to nearest whole number)

Depending on which you'd like. In C/C++ it would essentially be using Math.floor to convert to integer from float.

int to float:

var a = 10;
a.toFixed( 3 ); // result: 10.000
Dan Beam
  • 3,632
  • 2
  • 23
  • 27
  • 3
    That is not what he's looking. He's looking for the binary representation of a double. The '(int*)&a' in the question gives one a pointer to the machine-level (IEEE) bits of the double. – akauppi Apr 01 '12 at 13:08