diff --git a/src/Managed.UnitTests/PrecisionTest.cs b/src/Managed.UnitTests/PrecisionTest.cs index 54700a88..d9f95c24 100644 --- a/src/Managed.UnitTests/PrecisionTest.cs +++ b/src/Managed.UnitTests/PrecisionTest.cs @@ -482,6 +482,16 @@ namespace MathNet.Numerics.UnitTests Precision.AlmostEqual(1, 2, 0); } + [Test] + public void AlmostEqual() + { + AssertEx.That(()=>1.0.AlmostEqual(1.0), "1.0 equals 1.0."); + AssertEx.That(() => 1.0.AlmostEqual(1.0 + _doublePrecision), "1.0 equals 1.0 + 2^(-53)."); + AssertEx.That(() => 1.0.AlmostEqual(1.0 + _doublePrecision * 10), "1.0 equals 1.0 + 2^(-52)."); + AssertEx.That(() => !1.0.AlmostEqual(1.0 + _doublePrecision * 100), "1.0 does not equal 1.0 + 2^(-51)."); + AssertEx.That(() => !1.0.AlmostEqual(2.0), "1.0 does not equal 2.0"); + } + [Test] public void AlmostEqualWithMaxNumbersBetween() { diff --git a/src/Managed/Precision.cs b/src/Managed/Precision.cs index 7c0e6b63..32c46264 100644 --- a/src/Managed/Precision.cs +++ b/src/Managed/Precision.cs @@ -71,6 +71,32 @@ namespace MathNet.Numerics #endregion + #region Properties + /// + /// Gets the maximum relative precision of a double. + /// + /// The maximum relative precision of a double. + public static double DoubleMachinePrecision + { + get + { + return _doubleMachinePrecision; + } + } + + /// + /// Gets the maximum relative precision of a single. + /// + /// The maximum relative precision of a single. + public static double SingleMachinePrecision + { + get + { + return _singleMachinePrecision; + } + } + #endregion + #region Fields /// @@ -93,6 +119,9 @@ namespace MathNet.Numerics /// private static readonly int _numberOfDecimalPlacesForFloats; + /// Value representing 10 * 2^(-52) + private static readonly double _defaultRelativeAccuracy = _doubleMachinePrecision * 10; + #endregion /// @@ -670,6 +699,22 @@ namespace MathNet.Numerics return AlmostZero(a, _doubleMachinePrecision); } + /// + /// Checks whether two real numbers are almost equal. + /// + /// The first number + /// The second number + /// true if the two values differ by no more than 10 * 2^(-52); false otherwise. + public static bool AlmostEqual(this double a, double b) + { + if ((a == 0 && Math.Abs(b) < _defaultRelativeAccuracy) || (b == 0 && Math.Abs(a) < _defaultRelativeAccuracy)) + { + return true; + } + + return Math.Abs(a - b) < _defaultRelativeAccuracy * Math.Max(Math.Abs(a), Math.Abs(b)); + } + /// /// Compares two doubles and determines if they are equal to within the tolerance or not. Equality comparison is based on the binary representation. ///