Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting the exponent and mantissa of a Javascript Number

Tags:

Is there a reasonably fast way to extract the exponent and mantissa from a Number in Javascript?

AFAIK there's no way to get at the bits behind a Number in Javascript, which makes it seem to me that I'm looking at a factorization problem: finding m and n such that 2^n * m = k for a given k. Since integer factorization is in NP, I can only assume that this would be a fairly hard problem.

I'm implementing a GHC plugin for generating Javascript and need to implement the decodeFloat_Int# and decodeDouble_2Int# primitive operations; I guess I could just rewrite the parts of the base library that uses the operation to do wahtever they're doing in some other way (which shouldn't be too hard since all numeric types have Number as their representation anyway,) but it'd be nice if I didn't have to.

Is there any way to do this in an even remotely performant way, by some dark Javascript voodoo, clever mathematics or some other means, or should I just buckle down and have at the base library?

EDIT Based on ruakh's and Louis Wasserman's excellent answers, I came up with the following implementation, which seems to work well enough:

function getNumberParts(x) {     if(isNaN(x)) {         return {mantissa: -6755399441055744, exponent: 972};     }     var sig = x > 0 ? 1 : -1;     if(!isFinite(x)) {         return {mantissa: sig * 4503599627370496, exponent: 972};     }     x = Math.abs(x);     var exp = Math.floor(Math.log(x)*Math.LOG2E)-52;     var man = x/Math.pow(2, exp);     return {mantissa: sig*man, exponent: exp}; } 
like image 897
valderman Avatar asked Feb 21 '12 19:02

valderman


People also ask

How do you find the exponent and mantissa?

Thus, to find the real exponent, we have to subtract 127 from the given exponent. For example, if the mantissa is “10000000,” the real value of the mantissa is 128 − 127 = 1. The mantissa is 23 bits wide and represents the increasing negative powers of 2.

How do you find the exponent of a number in Javascript?

Using the Exponentiation OperatorThe exponentiation operator (**) can also be used to get the exponent power of a number. It returns a number which is the result of raising the first operand to the power of the second operand. It is the same as the Math. pow() method, discussed above.

What is mantissa and exponent in Java?

An exponent of all zeros indicates a denormalized floating-point number. Any other exponent indicates a normalized floating-point number. The mantissa contains one extra bit of precision beyond those that appear in the mantissa bits. The mantissa of a float, which occupies only 23 bits, has 24 bits of precision.


2 Answers

Using the new ArrayBuffer access arrays, it is actually possible to retrieve the exact mantissa and exponent, by extracting them from the Uint8Array. If you need more speed, consider reusing the Float64Array.

function getNumberParts(x) {     var float = new Float64Array(1),         bytes = new Uint8Array(float.buffer);      float[0] = x;      var sign = bytes[7] >> 7,         exponent = ((bytes[7] & 0x7f) << 4 | bytes[6] >> 4) - 0x3ff;      bytes[7] = 0x3f;     bytes[6] |= 0xf0;      return {         sign: sign,         exponent: exponent,         mantissa: float[0],     } } 

I've also created some test cases. 0 fails, since there is another representation for 2^-1023.

var tests = [1, -1, .123, -.123, 1.5, -1.5, 1e100, -1e100,                      1e-100, -1e-100, Infinity, -Infinity];  tests.forEach(function(x) {     var parts = getNumberParts(x),         value = Math.pow(-1, parts.sign) *                     Math.pow(2, parts.exponent) *                     parts.mantissa;      console.log("Testing: " + x + " " + value);     console.assert(x === value); });  console.log("Tests passed"); 
like image 149
copy Avatar answered Sep 30 '22 19:09

copy


ECMAScript doesn't define any straightforward way to do this; but for what it's worth, this isn't a "factorization problem" in the same sense as prime factorization.

What you want can theoretically be done very quickly by first handling the sign, then using a binary-tree approach (or logarithm) to find the exponent, and lastly dividing by the relevant power of two to get the mantissa; but unfortunately, it can be somewhat tricky to implement this in practice (what with special cases such as denormalized numbers). I recommend you read through section 8.5 of the ECMAScript specification to get a sense of what cases you'll have to handle.

like image 25
ruakh Avatar answered Sep 30 '22 18:09

ruakh