/// <summary> /// Reinterprets the memory contents of an integer value as a double precision /// floating point value /// </summary> /// <param name="value">Integer whose memory contents to reinterpret</param> /// <returns> /// The memory contents of the integer interpreted as a double precision /// floating point value /// </returns> public static double ReinterpretAsDouble(long value) { DoubleLongUnion union = new DoubleLongUnion(); union.Long = value; return(union.Double); }
/// <summary> /// Compares two numbers given some amount of allowed distance. /// https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ /// </summary> /// <param name="x">The first number.</param> /// <param name="y">The second number.</param> /// <param name="maxUlp">The number of discreet floating point values that are allowed between the two values.</param> /// <returns><c>true</c> if the two values are equal, otherwise false.</returns> public static bool Equals(double x, double y, int maxUlp) { if (maxUlp <= 0) { throw new ArgumentOutOfRangeException("Max Ulp must be greater than 0."); } DoubleLongUnion xUnion = new DoubleLongUnion { Double = x }; DoubleLongUnion yUnion = new DoubleLongUnion { Double = y }; // Convert to 2s complement if negative. ulong xSignMask = xUnion.ULong >> Precision.DOUBLE_SHIFT_BITS; ulong ySignMask = yUnion.ULong >> Precision.DOUBLE_SHIFT_BITS; ulong xTemp = ((Precision.DOUBLE_BIT_MASK - xUnion.ULong) & xSignMask); xUnion.ULong = xTemp | (xUnion.ULong & ~xSignMask); // Convert to 2s complement if negative. ulong yTemp = ((Precision.DOUBLE_BIT_MASK - yUnion.ULong) & ySignMask); yUnion.ULong = yTemp | (yUnion.ULong & ~ySignMask); // Return if the difference <= maxUlp return(Math.Abs(xUnion.Long - yUnion.Long) <= maxUlp); }
/// <summary> /// Reinterprets the memory contents of a double precision floating point /// value as an integer value /// </summary> /// <param name="value"> /// Double precision floating point value whose memory contents to reinterpret /// </param> /// <returns> /// The memory contents of the double precision floating point value /// interpreted as an integer /// </returns> public static long ReinterpretAsLong(double value) { DoubleLongUnion union = new DoubleLongUnion(); union.Double = value; return(union.Long); }
public static double ReinterpretAsDouble(long value) { DoubleLongUnion doubleLongUnion = default(DoubleLongUnion); doubleLongUnion.Long = value; return(doubleLongUnion.Double); }
public static long ReinterpretAsLong(double value) { DoubleLongUnion doubleLongUnion = default(DoubleLongUnion); doubleLongUnion.Double = value; return(doubleLongUnion.Long); }
/// <summary>Compares two double precision floating point values for equality</summary> /// <param name="left">First double precision floating point value to be compared</param> /// <param name="right">Second double precision floating point value t be compared</param> /// <param name="maxUlps"> /// Maximum number of representable double precision floating point values that are /// allowed to be between the left and the right double precision floating point values /// </param> /// <returns>True if both numbers are equal or close to being equal</returns> /// <remarks> /// <para> /// Double precision floating point values can only represent a limited series of /// natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 /// can be stored in a double, but nothing between them. /// </para> /// <para> /// This comparison will count how many possible double precision floating point /// values are between the left and the right number. If the number of possible /// values between both numbers is less than or equal to maxUlps, then the numbers /// are considered as being equal. /// </para> /// <para> /// Implementation partially follows the code outlined here: /// http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ /// </para> /// </remarks> public static bool AreAlmostEqualUlps(double left, double right, long maxUlps) { DoubleLongUnion leftUnion = new DoubleLongUnion(); DoubleLongUnion rightUnion = new DoubleLongUnion(); leftUnion.Double = left; rightUnion.Double = right; ulong leftSignMask = (leftUnion.ULong >> 63); ulong rightSignMask = (rightUnion.ULong >> 63); ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask); leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask); ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask); rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask); if (leftSignMask != rightSignMask) // Overflow possible, check each against zero { if (Math.Abs(leftUnion.Long) > maxUlps || Math.Abs(rightUnion.Long) > maxUlps) { return(false); } } // Either they have the same sign or both are very close to zero return(Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps); }
static double Int64BitsToDouble(long value) { var union = new DoubleLongUnion { Int64 = value }; return(union.Double); }
static long DoubleToInt64Bits(double value) { var union = new DoubleLongUnion { Double = value }; return(union.Int64); }
/// <summary> /// Gets the binary representation of <see cref="double"/> <paramref name="number"/>. /// </summary> public static string GetBinaryRepresentation(this double number) { DoubleLongUnion union = new DoubleLongUnion { Double = number }; ulong bits = union.Ulong; return(ConvertToString(bits)); }
public static bool AreAlmostEqualUlps(double left, double right, long maxUlps) { DoubleLongUnion doubleLongUnion = default(DoubleLongUnion); DoubleLongUnion doubleLongUnion2 = default(DoubleLongUnion); doubleLongUnion.Double = left; doubleLongUnion2.Double = right; ulong num = doubleLongUnion.ULong >> 63; ulong num2 = doubleLongUnion2.ULong >> 63; ulong num3 = (9223372036854775808uL - doubleLongUnion.ULong) & num; doubleLongUnion.ULong = num3 | (doubleLongUnion.ULong & ~num); ulong num4 = (9223372036854775808uL - doubleLongUnion2.ULong) & num2; doubleLongUnion2.ULong = num4 | (doubleLongUnion2.ULong & ~num2); return(Math.Abs(doubleLongUnion.Long - doubleLongUnion2.Long) <= maxUlps); }
public static bool AreAlmostEqualUlps(double left, double right, long maxUlps) { DoubleLongUnion doubleLongUnion1 = new DoubleLongUnion(); DoubleLongUnion doubleLongUnion2 = new DoubleLongUnion(); doubleLongUnion1.Double = left; doubleLongUnion2.Double = right; ulong num1 = doubleLongUnion1.ULong >> 63; ulong num2 = doubleLongUnion2.ULong >> 63; ulong num3 = 9223372036854775808UL - doubleLongUnion1.ULong & num1; doubleLongUnion1.ULong = num3 | doubleLongUnion1.ULong & ~num1; ulong num4 = 9223372036854775808UL - doubleLongUnion2.ULong & num2; doubleLongUnion2.ULong = num4 | doubleLongUnion2.ULong & ~num2; return(Math.Abs(doubleLongUnion1.Long - doubleLongUnion2.Long) <= maxUlps); }
/// <summary>Compares two double precision floating point values for equality</summary> /// <param name="left">First double precision floating point value to be compared</param> /// <param name="right">Second double precision floating point value t be compared</param> /// <param name="maxUlps"> /// Maximum number of representable double precision floating point values that are /// allowed to be between the left and the right double precision floating point values /// </param> /// <returns>True if both numbers are equal or close to being equal</returns> /// <remarks> /// <para> /// Double precision floating point values can only represent a limited series of /// natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 /// can be stored in a double, but nothing inbetween them. /// </para> /// <para> /// This comparison will count how many possible double precision floating point /// values are between the left and the right number. If the number of possible /// values between both numbers is less than or equal to maxUlps, then the numbers /// are considered as being equal. /// </para> /// <para> /// Implementation partially follows the code outlined here: /// http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ /// </para> /// </remarks> public static bool AreAlmostEqualUlps(double left, double right, long maxUlps) { DoubleLongUnion leftUnion = new DoubleLongUnion(); DoubleLongUnion rightUnion = new DoubleLongUnion(); leftUnion.Double = left; rightUnion.Double = right; ulong leftSignMask = (leftUnion.ULong >> 63); ulong rightSignMask = (rightUnion.ULong >> 63); ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask); leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask); ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask); rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask); return(Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps); }
/// <summary> /// Convert double number to binary string /// </summary> /// <param name="number"></param> /// <returns>Binary string</returns> public static string GetBinaryString(this double number) { long longBytes = new DoubleLongUnion { Double = number }.Long; string resultString = string.Empty; for (int i = 0; i < DoubleBits; i++) { if (longBytes == longBytes >> 1 << 1) { resultString = "0" + resultString; } else { resultString = "1" + resultString; } longBytes >>= 1; } return(resultString); }
/// <summary>Compares two double precision floating point values for equality</summary> /// <param name="left">First double precision floating point value to be compared</param> /// <param name="right">Second double precision floating point value t be compared</param> /// <param name="maxUlps"> /// Maximum number of representable double precision floating point values that are /// allowed to be between the left and the right double precision floating point values /// </param> /// <returns>True if both numbers are equal or close to being equal</returns> /// <remarks> /// <para> /// Double precision floating point values can only represent a limited series of /// natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 /// can be stored in a double, but nothing between them. /// </para> /// <para> /// This comparison will count how many possible double precision floating point /// values are between the left and the right number. If the number of possible /// values between both numbers is less than or equal to maxUlps, then the numbers /// are considered as being equal. /// </para> /// <para> /// Implementation partially follows the code outlined here: /// http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ /// </para> /// </remarks> public static bool AreAlmostEqualUlps(double left, double right, long maxUlps) { DoubleLongUnion leftUnion = new DoubleLongUnion(); DoubleLongUnion rightUnion = new DoubleLongUnion(); leftUnion.Double = left; rightUnion.Double = right; ulong leftSignMask = (leftUnion.ULong >> 63); ulong rightSignMask = (rightUnion.ULong >> 63); ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask); leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask); ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask); rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask); if (leftSignMask != rightSignMask) // Overflow possible, check each against zero { // This check is specifically used to trap the case of 0 == -0 // In IEEE floating point maths, -0 is converted to Double.MinValue, which cannot be used with // Math.Abs(...) below due to overflow issues. This should only match the 0 == -0 condition. if (left == right) { return(true); } if (Math.Abs(leftUnion.Long) > maxUlps || Math.Abs(rightUnion.Long) > maxUlps) { return(false); } } // Either they have the same sign or both are very close to zero return(Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps); }
/// <summary> /// Reinterprets the memory contents of an integer value as a double precision /// floating point value /// </summary> /// <param name="value">Integer whose memory contents to reinterpret</param> /// <returns> /// The memory contents of the integer interpreted as a double precision /// floating point value /// </returns> public static double ReinterpretAsDouble(long value) { DoubleLongUnion union = new DoubleLongUnion(); union.Long = value; return union.Double; }
/// <summary> /// Reinterprets the memory contents of a double precision floating point /// value as an integer value /// </summary> /// <param name="value"> /// Double precision floating point value whose memory contents to reinterpret /// </param> /// <returns> /// The memory contents of the double precision floating point value /// interpreted as an integer /// </returns> public static long ReinterpretAsLong(double value) { DoubleLongUnion union = new DoubleLongUnion(); union.Double = value; return union.Long; }
/// <summary>Compares two double precision floating point values for equality</summary> /// <param name="left">First double precision floating point value to be compared</param> /// <param name="right">Second double precision floating point value t be compared</param> /// <param name="maxUlps"> /// Maximum number of representable double precision floating point values that are /// allowed to be between the left and the right double precision floating point values /// </param> /// <returns>True if both numbers are equal or close to being equal</returns> /// <remarks> /// <para> /// Double precision floating point values can only represent a limited series of /// natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 /// can be stored in a double, but nothing inbetween them. /// </para> /// <para> /// This comparison will count how many possible double precision floating point /// values are between the left and the right number. If the number of possible /// values between both numbers is less than or equal to maxUlps, then the numbers /// are considered as being equal. /// </para> /// <para> /// Implementation partially follows the code outlined here: /// http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ /// </para> /// </remarks> public static bool AreAlmostEqualUlps(double left, double right, long maxUlps) { DoubleLongUnion leftUnion = new DoubleLongUnion(); DoubleLongUnion rightUnion = new DoubleLongUnion(); leftUnion.Double = left; rightUnion.Double = right; ulong leftSignMask = (leftUnion.ULong >> 63); ulong rightSignMask = (rightUnion.ULong >> 63); ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask); leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask); ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask); rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask); return (Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps); }
/// <summary>Compares two double precision floating point _values for equality</summary> /// <param name="left">First double precision floating point value to be compared</param> /// <param name="right">Second double precision floating point value t be compared</param> /// <param name="maxUlps"> /// Maximum number of representable double precision floating point _values that are /// allowed to be between the left and the right double precision floating point _values /// </param> /// <returns>True if both numbers are equal or close to being equal</returns> /// <remarks> /// <para> /// Double precision floating point _values can only represent a limited series of /// natural numbers. For example, the _values 2.0000000000000000 and 2.0000000000000004 /// can be stored in a double, but nothing inbetween them. /// </para> /// <para> /// This comparison will count how many possible double precision floating point /// _values are between the left and the right number. If the number of possible /// _values between both numbers is less than or equal to maxUlps, then the numbers /// are considered as being equal. /// </para> /// <para> /// Implementation partially follows the code outlined here: /// http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ /// </para> /// </remarks> public static bool AreAlmostEqualUlps(double left, double right, long maxUlps) { DoubleLongUnion leftUnion = new DoubleLongUnion(); DoubleLongUnion rightUnion = new DoubleLongUnion(); leftUnion.Double = left; rightUnion.Double = right; ulong leftSignMask = (leftUnion.ULong >> 63); ulong rightSignMask = (rightUnion.ULong >> 63); ulong leftTemp = ((0x8000000000000000 - leftUnion.ULong) & leftSignMask); leftUnion.ULong = leftTemp | (leftUnion.ULong & ~leftSignMask); ulong rightTemp = ((0x8000000000000000 - rightUnion.ULong) & rightSignMask); rightUnion.ULong = rightTemp | (rightUnion.ULong & ~rightSignMask); if (leftSignMask != rightSignMask) // Overflow possible, check each against zero { if (Math.Abs(leftUnion.Long) > maxUlps || Math.Abs(rightUnion.Long) > maxUlps) return false; } // Either they have the same sign or both are very close to zero return Math.Abs(leftUnion.Long - rightUnion.Long) <= maxUlps; }