Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting mantissa and exponent from double in c#

Is there any straightforward way to get the mantissa and exponent from a double in c# (or .NET in general)?

I found this example using Google, but I'm not sure how robust it would be. Could the binary representation for a double change in some future version of the framework, etc?

The other alternative I found was to use System.Decimal instead of double and use the Decimal.GetBits() method to extract them.

Any suggestions?

like image 692
dvenema Avatar asked Dec 23 '08 20:12

dvenema


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 mantissa in floating point in C?

This is done by adjusting the exponent, e.g. etc. The mantissa is usually represented in base b, as a binary fraction. So (in a very low-precision format), 1 would be 1.000*20, 2 would be 1.000*21, and 0.375 would be 1.100*2-2, where the first 1 after the decimal point counts as 1/2, the second as 1/4, etc.

What is the mantissa value in double precision?

In double precision, 52 bits are used for mantissa. Bias number is 127.


2 Answers

The binary format shouldn't change - it would certainly be a breaking change to existing specifications. It's defined to be in IEEE754 / IEC 60559:1989 format, as Jimmy said. (C# 3.0 language spec section 1.3; ECMA 335 section 8.2.2). The code in DoubleConverter should be fine and robust.

For the sake of future reference, the relevant bit of the code in the example is:

public static string ToExactString (double d) {     …      // Translate the double into sign, exponent and mantissa.     long bits = BitConverter.DoubleToInt64Bits(d);     // Note that the shift is sign-extended, hence the test against -1 not 1     bool negative = (bits & (1L << 63)) != 0;     int exponent = (int) ((bits >> 52) & 0x7ffL);     long mantissa = bits & 0xfffffffffffffL;      // Subnormal numbers; exponent is effectively one higher,     // but there's no extra normalisation bit in the mantissa     if (exponent==0)     {         exponent++;     }     // Normal numbers; leave exponent as it is but add extra     // bit to the front of the mantissa     else     {         mantissa = mantissa | (1L << 52);     }      // Bias the exponent. It's actually biased by 1023, but we're     // treating the mantissa as m.0 rather than 0.m, so we need     // to subtract another 52 from it.     exponent -= 1075;      if (mantissa == 0)      {         return negative ? "-0" : "0";     }      /* Normalize */     while((mantissa & 1) == 0)      {    /*  i.e., Mantissa is even */         mantissa >>= 1;         exponent++;     }      … } 

The comments made sense to me at the time, but I'm sure I'd have to think for a while about them now. After the very first part you've got the "raw" exponent and mantissa - the rest of the code just helps to treat them in a simpler fashion.

like image 121
Jon Skeet Avatar answered Oct 05 '22 11:10

Jon Skeet


The representation is a IEEE standard and shouldn't change.

https://msdn.microsoft.com/en-us/library/system.double(v=vs.110).aspx

The Double type complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic.

EDIT: The reason why decimal has a getBits and double does not is that decimal preserves significant digits. 3.0000m == 3.00m but the exponents/mantissas are actually different. I think floats/doubles are uniquely represented.

like image 36
Jimmy Avatar answered Oct 05 '22 12:10

Jimmy