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?
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.
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.
In double precision, 52 bits are used for mantissa. Bias number is 127.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With