javac++cfloating-pointmath.h

Is there a Java equivalent of frexp?


Is there a Java equivalent of the C / C++ function called frexp? If you aren't familiar, frexp is defined by Wikipedia to "break floating-point number down into mantissa and exponent."

I am looking for an implementation with both speed and accuracy but I would rather have the accuracy if I could only choose one.

This is the code sample from the first reference. It should make the frexp contract a little more clear:

/* frexp example */
#include <stdio.h>
#include <math.h>

int main ()
{
  double param, result;
  int n;

  param = 8.0;
  result = frexp (param , &n);
  printf ("%lf * 2^%d = %f\n", result, n, param);
  return 0;
}

/* Will produce: 0.500000 * 2^4 = 8.000000 */

Solution

  • How's this?

    public static class FRexpResult
    {
       public int exponent = 0;
       public double mantissa = 0.;
    }
    
    public static FRexpResult frexp(double value)
    {
       final FRexpResult result = new FRexpResult();
       long bits = Double.doubleToLongBits(value);
       double realMant = 1.;
    
       // Test for NaN, infinity, and zero.
       if (Double.isNaN(value) || 
           value + value == value || 
           Double.isInfinite(value))
       {
          result.exponent = 0;
          result.mantissa = value;
       }
       else
       {
    
          boolean neg = (bits < 0);
          int exponent = (int)((bits >> 52) & 0x7ffL);
          long mantissa = bits & 0xfffffffffffffL;
    
          if(exponent == 0)
          {
             exponent++;
          }
          else
          {
             mantissa = mantissa | (1L<<52);
          }
    
          // bias the exponent - actually biased by 1023.
          // we are treating the mantissa as m.0 instead of 0.m
          //  so subtract another 52.
          exponent -= 1075;
          realMant = mantissa;
    
          // normalize
          while(realMant > 1.0) 
          {
             mantissa >>= 1;
             realMant /= 2.;
             exponent++;
          }
    
          if(neg)
          {
             realMant = realMant * -1;
          }
    
          result.exponent = exponent;
          result.mantissa = realMant;
       }
       return result;
    }
    

    This is "inspired" or actually nearly copied identically from an answer to a similar C# question. It works with the bits and then makes the mantissa a number between 1.0 and 0.0.