/// <summary> /// Returns a new instance BigInteger structure from a 64-bit double precision floating /// point value. /// </summary> /// <param name="value"> A 64-bit double precision floating point value. </param> /// <returns> The corresponding BigInteger value. </returns> public double ToDouble() { // Special case: zero. if (this.wordCount == 1 && this.bits[0] == 0) { return(0.0); } // Get the number of bits in the BigInteger. var bitCount = this.BitCount; // The top 53 bits can be packed into the double (the top-most bit is implied). var temp = BigInteger.RightShift(this, bitCount - 53); ulong doubleBits = (((ulong)temp.bits[1] << 32) | temp.bits[0]) & 0xFFFFFFFFFFFFF; // Base-2 exponent is however much we shifted, plus 52 (because the decimal point is // effectively at the 52nd bit), plus 1023 (the bias). doubleBits |= (ulong)(bitCount - 53 + 52 + 1023) << 52; // Handle the sign bit. if (this.sign == -1) { doubleBits |= (ulong)1 << 63; } // Convert the bit representation to a double. return(XBitConverter.Int64BitsToDouble((long)doubleBits)); }
/// <summary> /// Calculates the minimum increment that creates a number distinct from the value that was /// provided. The error for the number is plus or minus half the result of this method /// (note that the number returned by this method may be so small that dividing it by two /// produces zero). /// </summary> /// <param name="value"> The number to calculate an error value for. </param> /// <returns> The minimum increment that creates a number distinct from the value that was /// provided. </returns> private static double CalculateError(double value) { long bits = XBitConverter.DoubleToInt64Bits(value); // Extract the base-2 exponent. var base2Exponent = (int)((bits & 0x7FF0000000000000) >> 52); // Handle denormals. if (base2Exponent == 0) { return(double.Epsilon); } // Handle very small numbers. if (base2Exponent < 53) { return(XBitConverter.Int64BitsToDouble(1L << (base2Exponent - 1))); } // Subtract 52 from the exponent to get the error (52 is the number of bits in the mantissa). return(XBitConverter.Int64BitsToDouble((long)(base2Exponent - 52) << 52)); }
/// <summary> /// Adds ULPs (units in the last place) to the given double-precision number. /// </summary> /// <param name="value"> The value to modify. </param> /// <param name="ulps"> The number of ULPs to add. Can be negative. </param> /// <returns> The modified number. </returns> private static double AddUlps(double value, int ulps) { // Note: overflow or underflow in mantissa carries over to the exponent. // Overflow or underflow in exponent produces infinity or zero. return(XBitConverter.Int64BitsToDouble(XBitConverter.DoubleToInt64Bits(value) + ulps)); }