Jump to content

IBM hexadecimal floating-point

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by 65.206.3.249 (talk) at 20:48, 19 March 2004. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

IBM 64 bit Floating Point Standard

IBM uses the same basic formula

double = mantissa * base ^ exponent

with the following differences


The manissa has increased at the expence of the exponent:

 1     7                               56
+-+-----------+----------------------------------------------------+
|S|  Exp      |  Fraction                                          |
+-+-----------+----------------------------------------------------+
63 62       56 55                                                 0

The bias is now 64 because the exponent is smaller. Finally the base in IBM is 16 not 2. This is the same as shifting the exponent by 2 (multiply by 4) but still leaves the IBM exponent slightly smaller than the equivalent in IEEE. IBM does NOT suppress the initial bit. IBM always puts the radix point to the left of the mantissa.

Converting from IBM to/from IEEE

Here is some Java code that has been tested and works for converting IBM to/from IEEE. It does not handle the special cases of NA, and infinities. That should be added eventually

   // Thom_Burnett@CognigenCorp.com
   public static double ibmFloat64ToDouble( long ibmFloat ) {
       double ieeeDouble = 0;
       long sign = ibmFloat & MASK_SIGN_64;
       long mantissaIbm = ibmFloat & MASK_MANT_IBM_64;
       long exponentIbm = ibmFloat & MASK_EXP_IBM_64;
       long exponentIeee = exponentIbm ;
       // The IBM exponent is 7 bits, biased 64, and used with base 64. The IEEE exponent is 11 bits, biased 1023, and used with base 2

// Move the exponent to last part of long so that we can do arithemtic with it.

       exponentIeee >>>= IBM_MANTISSA_SIZE ; 
       exponentIeee -= IBM_EXPONENT_BIAS ;
       exponentIeee *= IEEE_TO_IBM_BASE ; // Change from base 2 -> base 16
       long mantissaIeee = mantissaIbm ;
       while ((mantissaIeee & MASK_IBM_MANTISSA_LEAD_BIT) == 0 ) {
           mantissaIeee = mantissaIeee << 1 ; // Remove the zero bits
           exponentIeee -= 1 ;
       }
       // One more time to remove the lead bit
       mantissaIeee = mantissaIeee << 1 ; // Remove the zero bits
       exponentIeee -= 1 ;
       mantissaIeee = mantissaIeee >> IBM_MANTISSA_SIZE - IEEE_MANTISSA_SIZE ; // Move the mantissa from IBM (56th bit) -> IEEE start (52nd bit)
       exponentIeee += IEEE_EXPONENT_BIAS ;
       exponentIeee = exponentIeee << IEEE_MANTISSA_SIZE ; // put it back
       long ieeeLong = (sign & MASK_SIGN_64) | (exponentIeee & MASK_EXP_IEEE_64) | (MASK_MANT_IEEE_64 & mantissaIeee) ;
       ieeeDouble = Double.longBitsToDouble(ieeeLong) ;
       return ieeeDouble;
   }
   static public long doubleToIbmFloatAsLong(double incomingDouble) {
       long ieeeDouble = Double.doubleToLongBits(incomingDouble) ;
       // Convert the exponent from IEEE to IBM
       long ieeeExponent = ieeeDouble & MASK_EXP_IEEE_64 ;
       ieeeExponent = ieeeExponent >>> IEEE_MANTISSA_SIZE ;
       ieeeExponent = ieeeExponent - IEEE_EXPONENT_BIAS ;
       long ibmSign = ieeeDouble & MASK_SIGN_64 ;
       long ieeeMantissa = ieeeDouble & MASK_MANT_IEEE_64 ;

ieeeMantissa = activateBit(ieeeMantissa, (int)IEEE_MANTISSA_SIZE) ; // Turn on the 1st bit for ibm since it doesn't suppress this bit long mantissaShiftNeededForBase16 = ieeeExponent % IEEE_TO_IBM_BASE ; while(mantissaShiftNeededForBase16 < 0) { mantissaShiftNeededForBase16 += IEEE_TO_IBM_BASE ; } ieeeMantissa = ieeeMantissa << mantissaShiftNeededForBase16 ; // I think there are two conflicting shifts. 4 to the left to move the mantissa // and 4 to the right because IBM using base 16 has smaller mantissas.

       long ibmMantissa = ieeeMantissa ; //<< (IBM_MANTISSA_SIZE - IEEE_MANTISSA_SIZE) ;
       //ibmMantissa = ibmMantissa >> 1 ; // Move right 1 bit to fit the left of radix 1

long ibmExponent = ieeeExponent / IEEE_TO_IBM_BASE ; if(ieeeExponent >= 0) { ibmExponent++ ; // Move up one to cover the suppressed ieee bit }

ibmExponent += IBM_EXPONENT_BIAS ; ibmExponent = ibmExponent << IBM_MANTISSA_SIZE ;

       long ibmFloatAsLong = ibmSign | ( ibmExponent & MASK_EXP_IBM_64 ) | ( ibmMantissa & MASK_MANT_IBM_64 ) ;
       return ibmFloatAsLong ;
   }