diff --git a/src/Numerics/Precision.cs b/src/Numerics/Precision.cs
index 66136719..1c1d890c 100644
--- a/src/Numerics/Precision.cs
+++ b/src/Numerics/Precision.cs
@@ -165,12 +165,12 @@ namespace MathNet.Numerics
///
static Precision()
{
- _numberOfDecimalPlacesForFloats = (int)Math.Ceiling(Math.Abs(Math.Log10(_singleMachinePrecision)));
- _numberOfDecimalPlacesForDoubles = (int)Math.Ceiling(Math.Abs(Math.Log10(_doubleMachinePrecision)));
+ _numberOfDecimalPlacesForFloats = (int)Math.Floor(Math.Abs(Math.Log10(_singleMachinePrecision)));
+ _numberOfDecimalPlacesForDoubles = (int)Math.Floor(Math.Abs(Math.Log10(_doubleMachinePrecision)));
}
///
- /// Gets the number of decimal places for floats.
+ /// Gets the number of fully significant decimal places for floats.
///
/// The number of decimal places for floats.
public static int NumberOfDecimalPlacesForFloats
@@ -182,7 +182,7 @@ namespace MathNet.Numerics
}
///
- /// Gets the number of decimal places for doubles.
+ /// Gets the number of fully significant decimal places for doubles.
///
/// The number of decimal places for doubles.
public static int NumberOfDecimalPlacesForDoubles
@@ -211,27 +211,18 @@ namespace MathNet.Numerics
double magnitude = Math.Log10(Math.Abs(value));
#if PORTABLE
- // To get the right number we need to know if the value is negative or positive
- // truncating a positive number will always give use the correct magnitude
- // truncating a negative number will give us a magnitude that is off by 1
- if (magnitude < 0)
- {
+ var truncated = (int)Truncate(magnitude);
+#else
- return (int)Truncate(magnitude - 1);
- }
+ var truncated = (int)Math.Truncate(magnitude);
+#endif
- return (int)Truncate(magnitude);
-#else
// To get the right number we need to know if the value is negative or positive
// truncating a positive number will always give use the correct magnitude
- // truncating a negative number will give us a magnitude that is off by 1
- if (magnitude < 0)
- {
- return (int)Math.Truncate(magnitude - 1);
- }
-
- return (int)Math.Truncate(magnitude);
-#endif
+ // truncating a negative number will give us a magnitude that is off by 1 (unless integer)
+ return magnitude < 0d && truncated != magnitude
+ ? truncated - 1
+ : truncated;
}
@@ -252,24 +243,21 @@ namespace MathNet.Numerics
// work for negative numbers (obviously).
var magnitude = Convert.ToSingle(Math.Log10(Math.Abs(value)));
- // To get the right number we need to know if the value is negative or positive
- // truncating a positive number will always give use the correct magnitude
- // truncating a negative number will give us a magnitude that is off by 1
- if (magnitude < 0)
- {
#if PORTABLE
- return (int)Truncate(magnitude - 1);
+ var truncated = (int)Truncate(magnitude);
#else
- return (int)Math.Truncate(magnitude - 1);
-#endif
- }
-#if PORTABLE
- return (int)Truncate(magnitude);
-#else
- return (int)Math.Truncate(magnitude);
+ var truncated = (int)Math.Truncate(magnitude);
#endif
+
+ // To get the right number we need to know if the value is negative or positive
+ // truncating a positive number will always give use the correct magnitude
+ // truncating a negative number will give us a magnitude that is off by 1 (unless integer)
+ return magnitude < 0f && truncated != magnitude
+ ? truncated - 1
+ : truncated;
}
+
///
/// Returns the number divided by it's magnitude, effectively returning a number between -10 and 10.
///
@@ -1174,7 +1162,7 @@ namespace MathNet.Numerics
///
public static bool AlmostEqualInDecimalPlaces(this double a, double b, int decimalPlaces)
{
- if (decimalPlaces <= 0)
+ if (decimalPlaces < 0)
{
// Can't have a negative number of decimal places
throw new ArgumentOutOfRangeException("decimalPlaces");
@@ -1197,7 +1185,7 @@ namespace MathNet.Numerics
if (Math.Abs(a) < _doubleMachinePrecision || Math.Abs(b) < _doubleMachinePrecision)
{
- return AlmostEqualWithAbsoluteDecimalPlaces(a, b, decimalPlaces);
+ return AlmostEqualInAbsoluteDecimalPlaces(a, b, decimalPlaces);
}
// If both numbers are equal, get out now. This should remove the possibility of both numbers being zero
@@ -1207,7 +1195,7 @@ namespace MathNet.Numerics
return true;
}
- return AlmostEqualWithRelativeDecimalPlaces(a, b, decimalPlaces);
+ return AlmostEqualInRelativeDecimalPlaces(a, b, decimalPlaces);
}
///
@@ -1230,7 +1218,7 @@ namespace MathNet.Numerics
///
public static bool AlmostEqualInDecimalPlaces(this float a, float b, int decimalPlaces)
{
- if (decimalPlaces <= 0)
+ if (decimalPlaces < 0)
{
// Can't have a negative number of decimal places
throw new ArgumentOutOfRangeException("decimalPlaces");
@@ -1253,7 +1241,7 @@ namespace MathNet.Numerics
if (Math.Abs(a) < _singleMachinePrecision || Math.Abs(b) < _singleMachinePrecision)
{
- return AlmostEqualWithAbsoluteDecimalPlaces(a, b, decimalPlaces);
+ return AlmostEqualInAbsoluteDecimalPlaces(a, b, decimalPlaces);
}
// If both numbers are equal, get out now. This should remove the possibility of both numbers being zero
@@ -1263,7 +1251,7 @@ namespace MathNet.Numerics
return true;
}
- return AlmostEqualWithRelativeDecimalPlaces(a, b, decimalPlaces);
+ return AlmostEqualInRelativeDecimalPlaces(a, b, decimalPlaces);
}
///
@@ -1280,28 +1268,44 @@ namespace MathNet.Numerics
/// The second value.
/// The number of decimal places.
/// if both doubles are equal to each other within the specified number of decimal places; otherwise .
- public static bool AlmostEqualWithRelativeDecimalPlaces(this double a, double b, int decimalPlaces)
+ public static bool AlmostEqualInRelativeDecimalPlaces(this double a, double b, int decimalPlaces)
{
+ if (decimalPlaces < 0)
+ {
+ // Can't have a negative number of decimal places
+ throw new ArgumentOutOfRangeException("decimalPlaces");
+ }
+
+ // If A or B are a NAN, return false. NANs are equal to nothing,
+ // not even themselves.
+ if (double.IsNaN(a) || double.IsNaN(b))
+ {
+ return false;
+ }
+
+ // If A or B are infinity (positive or negative) then
+ // only return true if they are exactly equal to each other -
+ // that is, if they are both infinities of the same sign.
+ if (double.IsInfinity(a) || double.IsInfinity(b))
+ {
+ return a == b;
+ }
+
// If the magnitudes of the two numbers are equal to within one magnitude the numbers could potentially be equal
int magnitudeOfFirst = Magnitude(a);
int magnitudeOfSecond = Magnitude(b);
- if (Math.Max(magnitudeOfFirst, magnitudeOfSecond) > (Math.Min(magnitudeOfFirst, magnitudeOfSecond) + 1))
+ int magnitudeOfMax = Math.Max(magnitudeOfFirst, magnitudeOfSecond);
+ if (magnitudeOfMax > (Math.Min(magnitudeOfFirst, magnitudeOfSecond) + 1))
{
return false;
}
- // Get the power of the number of decimalPlaces
- double decimalPlaceMagnitude = Math.Pow(10, -(decimalPlaces - 1));
-
// The values are equal if the difference between the two numbers is smaller than
// 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range
// on each side of the numbers, e.g. if decimalPlaces == 2,
- // then 0.01 will equal between 0.005 and 0.015, but not 0.02 and not 0.00
- double maxDifference = decimalPlaceMagnitude / 2.0;
-
- return a > b
- ? (a*Math.Pow(10, -magnitudeOfFirst)) - maxDifference < (b*Math.Pow(10, -magnitudeOfFirst))
- : (b*Math.Pow(10, -magnitudeOfSecond)) - maxDifference < (a*Math.Pow(10, -magnitudeOfSecond));
+ // then 0.01 will equal between 0.00995 and 0.01005, but not 0.0015 and not 0.0095
+ double decimalPlaceMagnitude = Math.Pow(10, magnitudeOfMax - decimalPlaces)/2d;
+ return Math.Abs((a - b)) < decimalPlaceMagnitude;
}
///
@@ -1318,28 +1322,44 @@ namespace MathNet.Numerics
/// The second value.
/// The number of decimal places.
/// if both floats are equal to each other within the specified number of decimal places; otherwise .
- public static bool AlmostEqualWithRelativeDecimalPlaces(this float a, float b, int decimalPlaces)
+ public static bool AlmostEqualInRelativeDecimalPlaces(this float a, float b, int decimalPlaces)
{
+ if (decimalPlaces < 0)
+ {
+ // Can't have a negative number of decimal places
+ throw new ArgumentOutOfRangeException("decimalPlaces");
+ }
+
+ // If A or B are a NAN, return false. NANs are equal to nothing,
+ // not even themselves.
+ if (float.IsNaN(a) || float.IsNaN(b))
+ {
+ return false;
+ }
+
+ // If A or B are infinity (positive or negative) then
+ // only return true if they are exactly equal to each other -
+ // that is, if they are both infinities of the same sign.
+ if (float.IsInfinity(a) || float.IsInfinity(b))
+ {
+ return a == b;
+ }
+
// If the magnitudes of the two numbers are equal to within one magnitude the numbers could potentially be equal
int magnitudeOfFirst = Magnitude(a);
int magnitudeOfSecond = Magnitude(b);
- if (Math.Max(magnitudeOfFirst, magnitudeOfSecond) > (Math.Min(magnitudeOfFirst, magnitudeOfSecond) + 1))
+ int magnitudeOfMax = Math.Max(magnitudeOfFirst, magnitudeOfSecond);
+ if (magnitudeOfMax > (Math.Min(magnitudeOfFirst, magnitudeOfSecond) + 1))
{
return false;
}
- // Get the power of the number of decimalPlaces
- var decimalPlaceMagnitude = (float)Math.Pow(10, -(decimalPlaces - 1));
-
// The values are equal if the difference between the two numbers is smaller than
// 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range
// on each side of the numbers, e.g. if decimalPlaces == 2,
- // then 0.01 will equal between 0.005 and 0.015, but not 0.02 and not 0.00
- float maxDifference = decimalPlaceMagnitude / 2.0f;
-
- return a > b
- ? (a*(float) Math.Pow(10, -magnitudeOfFirst)) - maxDifference < (b*(float) Math.Pow(10, -magnitudeOfFirst))
- : (b*(float) Math.Pow(10, -magnitudeOfSecond)) - maxDifference < (a*(float) Math.Pow(10, -magnitudeOfSecond));
+ // then 0.01 will equal between 0.00995 and 0.01005, but not 0.0015 and not 0.0095
+ var decimalPlaceMagnitude = (float) Math.Pow(10, magnitudeOfMax - decimalPlaces)/2d;
+ return Math.Abs((a - b)) < decimalPlaceMagnitude;
}
///
@@ -1348,7 +1368,7 @@ namespace MathNet.Numerics
///
///
///
- /// The values are equal if the difference between the two numbers is smaller than 10^(-numberOfDecimalPlaces). We divide by
+ /// The values are equal if the difference between the two numbers is smaller than 0.5e-decimalPlaces. We divide by
/// two so that we have half the range on each side of the numbers, e.g. if == 2, then 0.01 will equal between
/// 0.005 and 0.015, but not 0.02 and not 0.00
///
@@ -1357,15 +1377,29 @@ namespace MathNet.Numerics
/// The second value.
/// The number of decimal places.
/// if both doubles are equal to each other within the specified number of decimal places; otherwise .
- public static bool AlmostEqualWithAbsoluteDecimalPlaces(this double a, double b, int decimalPlaces)
+ public static bool AlmostEqualInAbsoluteDecimalPlaces(this double a, double b, int decimalPlaces)
{
- double decimalPlaceMagnitude = Math.Pow(10, -(decimalPlaces - 1));
-
+ // If A or B are a NAN, return false. NANs are equal to nothing,
+ // not even themselves.
+ if (double.IsNaN(a) || double.IsNaN(b))
+ {
+ return false;
+ }
+
+ // If A or B are infinity (positive or negative) then
+ // only return true if they are exactly equal to each other -
+ // that is, if they are both infinities of the same sign.
+ if (double.IsInfinity(a) || double.IsInfinity(b))
+ {
+ return a == b;
+ }
+
// The values are equal if the difference between the two numbers is smaller than
// 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range
// on each side of the numbers, e.g. if decimalPlaces == 2,
// then 0.01 will equal between 0.005 and 0.015, but not 0.02 and not 0.00
- return Math.Abs((a - b)) < decimalPlaceMagnitude / 2.0;
+ double decimalPlaceMagnitude = Math.Pow(10, -decimalPlaces)/2d;
+ return Math.Abs((a - b)) < decimalPlaceMagnitude;
}
///
@@ -1383,15 +1417,29 @@ namespace MathNet.Numerics
/// The second value.
/// The number of decimal places.
/// if both floats are equal to each other within the specified number of decimal places; otherwise .
- public static bool AlmostEqualWithAbsoluteDecimalPlaces(this float a, float b, int decimalPlaces)
+ public static bool AlmostEqualInAbsoluteDecimalPlaces(this float a, float b, int decimalPlaces)
{
- var decimalPlaceMagnitude = (float)Math.Pow(10, -(decimalPlaces - 1));
+ // If A or B are a NAN, return false. NANs are equal to nothing,
+ // not even themselves.
+ if (float.IsNaN(a) || float.IsNaN(b))
+ {
+ return false;
+ }
+
+ // If A or B are infinity (positive or negative) then
+ // only return true if they are exactly equal to each other -
+ // that is, if they are both infinities of the same sign.
+ if (float.IsInfinity(a) || float.IsInfinity(b))
+ {
+ return a == b;
+ }
// The values are equal if the difference between the two numbers is smaller than
// 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range
// on each side of the numbers, e.g. if decimalPlaces == 2,
// then 0.01 will equal between 0.005 and 0.015, but not 0.02 and not 0.00
- return Math.Abs((a - b)) < decimalPlaceMagnitude / 2.0f;
+ var decimalPlaceMagnitude = (float) Math.Pow(10, -decimalPlaces)/2f;
+ return Math.Abs((a - b)) < decimalPlaceMagnitude;
}
///
@@ -1849,4 +1897,4 @@ namespace MathNet.Numerics
}
#endif
}
-}
\ No newline at end of file
+}
diff --git a/src/UnitTests/AssertHelpers.cs b/src/UnitTests/AssertHelpers.cs
index 6b241759..49d5ed34 100644
--- a/src/UnitTests/AssertHelpers.cs
+++ b/src/UnitTests/AssertHelpers.cs
@@ -159,7 +159,7 @@ namespace MathNet.Numerics.UnitTests
return;
}
- if (!expected.AlmostEqualWithAbsoluteDecimalPlaces(actual, decimalPlaces))
+ if (!expected.AlmostEqualInAbsoluteDecimalPlaces(actual, decimalPlaces))
{
Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected, actual);
}
@@ -176,7 +176,7 @@ namespace MathNet.Numerics.UnitTests
return;
}
- if (!expected.AlmostEqualWithAbsoluteDecimalPlaces(actual, decimalPlaces))
+ if (!expected.AlmostEqualInAbsoluteDecimalPlaces(actual, decimalPlaces))
{
Assert.Fail("Not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected, actual);
}
@@ -187,12 +187,12 @@ namespace MathNet.Numerics.UnitTests
///
public static void AlmostEqualAbsolute(Complex expected, Complex actual, int decimalPlaces)
{
- if (!expected.Real.AlmostEqualWithAbsoluteDecimalPlaces(actual.Real, decimalPlaces))
+ if (!expected.Real.AlmostEqualInAbsoluteDecimalPlaces(actual.Real, decimalPlaces))
{
Assert.Fail("Real components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Real, actual.Real);
}
- if (!expected.Imaginary.AlmostEqualWithAbsoluteDecimalPlaces(actual.Imaginary, decimalPlaces))
+ if (!expected.Imaginary.AlmostEqualInAbsoluteDecimalPlaces(actual.Imaginary, decimalPlaces))
{
Assert.Fail("Imaginary components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Imaginary, actual.Imaginary);
}
@@ -203,12 +203,12 @@ namespace MathNet.Numerics.UnitTests
///
public static void AlmostEqualAbsolute(Complex32 expected, Complex32 actual, int decimalPlaces)
{
- if (!expected.Real.AlmostEqualWithAbsoluteDecimalPlaces(actual.Real, decimalPlaces))
+ if (!expected.Real.AlmostEqualInAbsoluteDecimalPlaces(actual.Real, decimalPlaces))
{
Assert.Fail("Real components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Real, actual.Real);
}
- if (!expected.Imaginary.AlmostEqualWithAbsoluteDecimalPlaces(actual.Imaginary, decimalPlaces))
+ if (!expected.Imaginary.AlmostEqualInAbsoluteDecimalPlaces(actual.Imaginary, decimalPlaces))
{
Assert.Fail("Imaginary components are not equal within {0} places. Expected:{1}; Actual:{2}", decimalPlaces, expected.Imaginary, actual.Imaginary);
}
diff --git a/src/UnitTests/PrecisionTest.cs b/src/UnitTests/PrecisionTest.cs
index 3c6025f3..d830d841 100644
--- a/src/UnitTests/PrecisionTest.cs
+++ b/src/UnitTests/PrecisionTest.cs
@@ -68,6 +68,13 @@ namespace MathNet.Numerics.UnitTests
Assert.AreEqual(11, 1e11.Magnitude());
Assert.AreEqual(12, 1e12.Magnitude());
+ Assert.AreEqual(-7, 1e-7.Magnitude());
+ Assert.AreEqual(-8, 1e-8.Magnitude());
+ Assert.AreEqual(-9, 1e-9.Magnitude());
+ Assert.AreEqual(-10, 1e-10.Magnitude());
+ Assert.AreEqual(-11, 1e-11.Magnitude());
+ Assert.AreEqual(-12, 1e-12.Magnitude());
+
Assert.AreEqual(5, 1.1e5.Magnitude());
Assert.AreEqual(-5, 2.2e-5.Magnitude());
Assert.AreEqual(9, 3.3e9.Magnitude());
@@ -95,6 +102,13 @@ namespace MathNet.Numerics.UnitTests
Assert.AreEqual(11, (-1e11).Magnitude());
Assert.AreEqual(12, (-1e12).Magnitude());
+ Assert.AreEqual(-7, (-1e-7).Magnitude());
+ Assert.AreEqual(-8, (-1e-8).Magnitude());
+ Assert.AreEqual(-9, (-1e-9).Magnitude());
+ Assert.AreEqual(-10, (-1e-10).Magnitude());
+ Assert.AreEqual(-11, (-1e-11).Magnitude());
+ Assert.AreEqual(-12, (-1e-12).Magnitude());
+
Assert.AreEqual(5, (-1.1e5).Magnitude());
Assert.AreEqual(-5, (-2.2e-5).Magnitude());
Assert.AreEqual(9, (-3.3e9).Magnitude());
@@ -686,50 +700,141 @@ namespace MathNet.Numerics.UnitTests
}
///
- /// AlmostEqual within decimal places with decimal places less than one throws ArgumentOutOfRangeException.
+ /// AlmostEqual within absolute decimal places.
///
[Test]
- public void AlmostEqualWithinDecimalPlacesWithDecimalPlacesLessThanOneThrowsArgumentOutOfRangeException()
+ public void AlmostEqualInAbsoluteDecimalPlaces()
{
- Assert.Throws(() => Precision.AlmostEqualInDecimalPlaces(1, 2, 0));
+ Assert.IsFalse(1d.AlmostEqualInAbsoluteDecimalPlaces(double.NaN, 2));
+ Assert.IsFalse(double.NaN.AlmostEqualInAbsoluteDecimalPlaces(2d, 2));
+ Assert.IsFalse(double.NaN.AlmostEqualInAbsoluteDecimalPlaces(double.NaN, 2));
+
+ Assert.IsFalse(double.NegativeInfinity.AlmostEqualInAbsoluteDecimalPlaces(2, 2));
+ Assert.IsFalse(1d.AlmostEqualInAbsoluteDecimalPlaces(double.NegativeInfinity, 2));
+ Assert.IsFalse(double.PositiveInfinity.AlmostEqualInAbsoluteDecimalPlaces(2, 2));
+ Assert.IsFalse(1d.AlmostEqualInAbsoluteDecimalPlaces(double.PositiveInfinity, 2));
+ Assert.IsFalse(double.NegativeInfinity.AlmostEqualInAbsoluteDecimalPlaces(double.PositiveInfinity, 2));
+ Assert.IsFalse(double.PositiveInfinity.AlmostEqualInAbsoluteDecimalPlaces(double.NegativeInfinity, 2));
+ Assert.IsTrue(double.PositiveInfinity.AlmostEqualInAbsoluteDecimalPlaces(double.PositiveInfinity, 2));
+ Assert.IsTrue(double.NegativeInfinity.AlmostEqualInAbsoluteDecimalPlaces(double.NegativeInfinity, 2));
+
+ // 1 -> +/- 0.05 (0.5e-1)
+ Assert.IsFalse(1d.AlmostEqualInAbsoluteDecimalPlaces(1.06, 1));
+ Assert.IsTrue(1d.AlmostEqualInAbsoluteDecimalPlaces(1.04, 1));
+ Assert.IsTrue(1d.AlmostEqualInAbsoluteDecimalPlaces(1.00, 1));
+ Assert.IsTrue(1d.AlmostEqualInAbsoluteDecimalPlaces(0.96, 1));
+ Assert.IsFalse(1d.AlmostEqualInAbsoluteDecimalPlaces(0.94, 1));
+ Assert.IsFalse(1d.AlmostEqualInAbsoluteDecimalPlaces(0.0, 1));
+
+ // -1 -> +/- 5 (0.5e+1)
+ Assert.IsFalse(100d.AlmostEqualInAbsoluteDecimalPlaces(106.0, -1));
+ Assert.IsTrue(100d.AlmostEqualInAbsoluteDecimalPlaces(104.0, -1));
+ Assert.IsTrue(100d.AlmostEqualInAbsoluteDecimalPlaces(100.0, -1));
+ Assert.IsTrue(100d.AlmostEqualInAbsoluteDecimalPlaces(96.0, -1));
+ Assert.IsFalse(100d.AlmostEqualInAbsoluteDecimalPlaces(94.0, -1));
+ Assert.IsFalse(100d.AlmostEqualInAbsoluteDecimalPlaces(0.0, -1));
+
+ // 3 -> +/- 0.0005 (0.5e-3)
+ Assert.IsFalse(0.01.AlmostEqualInAbsoluteDecimalPlaces(0.0106, 3));
+ Assert.IsTrue(0.01.AlmostEqualInAbsoluteDecimalPlaces(0.0104, 3));
+ Assert.IsTrue(0.01.AlmostEqualInAbsoluteDecimalPlaces(0.0100, 3));
+ Assert.IsTrue(0.01.AlmostEqualInAbsoluteDecimalPlaces(0.0096, 3));
+ Assert.IsFalse(0.01.AlmostEqualInAbsoluteDecimalPlaces(0.0094, 3));
+ Assert.IsFalse(0.01.AlmostEqualInAbsoluteDecimalPlaces(0.0, 3));
+
+ // 12 -> +/- 0.5e-12
+ Assert.IsTrue(0d.AlmostEqualInAbsoluteDecimalPlaces(4 * _doublePrecision, 12));
+ Assert.IsTrue(0d.AlmostEqualInAbsoluteDecimalPlaces(-4 * _doublePrecision, 12));
+ }
+
+ ///
+ /// AlmostEqual within relative decimal places.
+ ///
+ [Test]
+ public void AlmostEqualInRelativeDecimalPlaces()
+ {
+ Assert.IsFalse(1d.AlmostEqualInRelativeDecimalPlaces(double.NaN, 2));
+ Assert.IsFalse(double.NaN.AlmostEqualInRelativeDecimalPlaces(2d, 2));
+ Assert.IsFalse(double.NaN.AlmostEqualInRelativeDecimalPlaces(double.NaN, 2));
+
+ Assert.IsFalse(double.NegativeInfinity.AlmostEqualInRelativeDecimalPlaces(2, 2));
+ Assert.IsFalse(1d.AlmostEqualInRelativeDecimalPlaces(double.NegativeInfinity, 2));
+ Assert.IsFalse(double.PositiveInfinity.AlmostEqualInRelativeDecimalPlaces(2, 2));
+ Assert.IsFalse(1d.AlmostEqualInRelativeDecimalPlaces(double.PositiveInfinity, 2));
+ Assert.IsFalse(double.NegativeInfinity.AlmostEqualInRelativeDecimalPlaces(double.PositiveInfinity, 2));
+ Assert.IsFalse(double.PositiveInfinity.AlmostEqualInRelativeDecimalPlaces(double.NegativeInfinity, 2));
+ Assert.IsTrue(double.PositiveInfinity.AlmostEqualInRelativeDecimalPlaces(double.PositiveInfinity, 2));
+ Assert.IsTrue(double.NegativeInfinity.AlmostEqualInRelativeDecimalPlaces(double.NegativeInfinity, 2));
+
+ // 1 -> +/- max * 0.05 (0.5e-1)
+ Assert.IsTrue(1d.AlmostEqualInRelativeDecimalPlaces(1.04, 1));
+ Assert.IsFalse(1d.AlmostEqualInRelativeDecimalPlaces(1.06, 1));
+ Assert.IsTrue(1d.AlmostEqualInRelativeDecimalPlaces(0.96, 1));
+ Assert.IsFalse(1d.AlmostEqualInRelativeDecimalPlaces(0.94, 1));
+
+ // 1 -> +/- max * 0.05 (0.5e-1)
+ Assert.IsTrue(100d.AlmostEqualInRelativeDecimalPlaces(104.00, 1));
+ Assert.IsFalse(100d.AlmostEqualInRelativeDecimalPlaces(106.00, 1));
+ Assert.IsTrue(100d.AlmostEqualInRelativeDecimalPlaces(96.000, 1));
+ Assert.IsFalse(100d.AlmostEqualInRelativeDecimalPlaces(94.000, 1));
+
+ // 0 -> +/- max * 0.5 (0.5e-0)
+ Assert.IsTrue(0.01.AlmostEqualInRelativeDecimalPlaces(0.014, 0));
+ Assert.IsFalse(0.01.AlmostEqualInRelativeDecimalPlaces(0.016, 0));
+ Assert.IsTrue(0.01.AlmostEqualInRelativeDecimalPlaces(0.006, 0));
+ Assert.IsFalse(0.01.AlmostEqualInRelativeDecimalPlaces(0.004, 0));
+ }
+
+ ///
+ /// AlmostEqual within decimal places with negative decimal places throws ArgumentOutOfRangeException.
+ ///
+ [Test]
+ public void AlmostEqualInRelativeDecimalPlacesWithNegativeDecimalPlacesThrowsArgumentOutOfRangeException()
+ {
+ Assert.Throws(() => Precision.AlmostEqualInDecimalPlaces(1, 2, -1));
+ Assert.Throws(() => Precision.AlmostEqualInRelativeDecimalPlaces(1, 2, -1));
+ Assert.DoesNotThrow(() => Precision.AlmostEqualInAbsoluteDecimalPlaces(1, 2, -1));
}
///
/// AlmostEqual within decimal places.
///
[Test]
- public void AlmostEqualWithinDecimalPlaces()
+ public void AlmostEqualInDecimalPlaces()
{
- Assert.IsFalse(Precision.AlmostEqualInDecimalPlaces(1, double.NaN, 2));
+ Assert.IsFalse(1d.AlmostEqualInDecimalPlaces(double.NaN, 2));
Assert.IsFalse(double.NaN.AlmostEqualInDecimalPlaces(2, 2));
Assert.IsFalse(double.NaN.AlmostEqualInDecimalPlaces(double.NaN, 2));
Assert.IsFalse(double.NegativeInfinity.AlmostEqualInDecimalPlaces(2, 2));
- Assert.IsFalse(Precision.AlmostEqualInDecimalPlaces(1, double.NegativeInfinity, 2));
-
+ Assert.IsFalse(1d.AlmostEqualInDecimalPlaces(double.NegativeInfinity, 2));
Assert.IsFalse(double.PositiveInfinity.AlmostEqualInDecimalPlaces(2, 2));
- Assert.IsFalse(Precision.AlmostEqualInDecimalPlaces(1, double.PositiveInfinity, 2));
-
+ Assert.IsFalse(1d.AlmostEqualInDecimalPlaces(double.PositiveInfinity, 2));
Assert.IsFalse(double.NegativeInfinity.AlmostEqualInDecimalPlaces(double.PositiveInfinity, 2));
Assert.IsFalse(double.PositiveInfinity.AlmostEqualInDecimalPlaces(double.NegativeInfinity, 2));
-
Assert.IsTrue(double.PositiveInfinity.AlmostEqualInDecimalPlaces(double.PositiveInfinity, 2));
Assert.IsTrue(double.NegativeInfinity.AlmostEqualInDecimalPlaces(double.NegativeInfinity, 2));
- Assert.IsTrue(1.0.AlmostEqualInDecimalPlaces(1.04, 2));
- Assert.IsTrue(1.0.AlmostEqualInDecimalPlaces(0.96, 2));
-
- Assert.IsFalse(1.0.AlmostEqualInDecimalPlaces(1.06, 2));
- Assert.IsFalse(1.0.AlmostEqualInDecimalPlaces(0.94, 2));
-
- Assert.IsTrue(100.0.AlmostEqualInDecimalPlaces(104.00, 2));
- Assert.IsTrue(100.0.AlmostEqualInDecimalPlaces(96.000, 2));
-
- Assert.IsFalse(100.0.AlmostEqualInDecimalPlaces(106.00, 2));
- Assert.IsFalse(100.0.AlmostEqualInDecimalPlaces(94.000, 2));
-
- Assert.IsTrue(0.0.AlmostEqualInDecimalPlaces(4 * _doublePrecision, 12));
- Assert.IsTrue(0.0.AlmostEqualInDecimalPlaces(-4 * _doublePrecision, 12));
+ // 1 -> +/- max * 0.05 (0.5e-1)
+ Assert.IsTrue(1d.AlmostEqualInDecimalPlaces(1.04, 1));
+ Assert.IsFalse(1d.AlmostEqualInDecimalPlaces(1.06, 1));
+ Assert.IsTrue(1d.AlmostEqualInDecimalPlaces(0.96, 1));
+ Assert.IsFalse(1d.AlmostEqualInDecimalPlaces(0.94, 1));
+
+ // 1 -> +/- max * 0.05 (0.5e-1)
+ Assert.IsTrue(100d.AlmostEqualInDecimalPlaces(104.00, 1));
+ Assert.IsFalse(100d.AlmostEqualInDecimalPlaces(106.00, 1));
+ Assert.IsTrue(100d.AlmostEqualInDecimalPlaces(96.000, 1));
+ Assert.IsFalse(100d.AlmostEqualInDecimalPlaces(94.000, 1));
+
+ // 0 -> +/- max * 0.5 (0.5e-0)
+ Assert.IsTrue(0.01.AlmostEqualInDecimalPlaces(0.014, 0));
+ Assert.IsFalse(0.01.AlmostEqualInDecimalPlaces(0.016, 0));
+ Assert.IsTrue(0.01.AlmostEqualInDecimalPlaces(0.006, 0));
+ Assert.IsFalse(0.01.AlmostEqualInDecimalPlaces(0.004, 0));
+
+ Assert.IsTrue(0d.AlmostEqualInDecimalPlaces(4 * _doublePrecision, 12));
+ Assert.IsTrue(0d.AlmostEqualInDecimalPlaces(-4 * _doublePrecision, 12));
}
///
@@ -835,23 +940,21 @@ namespace MathNet.Numerics.UnitTests
Assert.IsFalse(double.PositiveInfinity.IsLargerWithDecimalPlaces(double.PositiveInfinity, 2));
Assert.IsFalse(double.NegativeInfinity.IsLargerWithDecimalPlaces(double.NegativeInfinity, 2));
- Assert.IsFalse(1.0.IsLargerWithDecimalPlaces(1.04, 2));
- Assert.IsFalse(1.0.IsLargerWithDecimalPlaces(0.96, 2));
-
- Assert.IsFalse(1.0.IsLargerWithDecimalPlaces(1.06, 2));
- Assert.IsTrue(1.0.IsLargerWithDecimalPlaces(0.94, 2));
+ Assert.IsFalse(1.0.IsLargerWithDecimalPlaces(1.006, 2));
+ Assert.IsFalse(1.0.IsLargerWithDecimalPlaces(1.004, 2));
+ Assert.IsFalse(1.0.IsLargerWithDecimalPlaces(0.996, 2));
+ Assert.IsTrue(1.0.IsLargerWithDecimalPlaces(0.994, 2));
- Assert.IsFalse(100.0.IsLargerWithDecimalPlaces(104.00, 2));
- Assert.IsFalse(100.0.IsLargerWithDecimalPlaces(96.000, 2));
+ Assert.IsFalse(100.0.IsLargerWithDecimalPlaces(100.6, 2));
+ Assert.IsFalse(100.0.IsLargerWithDecimalPlaces(100.4, 2));
+ Assert.IsFalse(100.0.IsLargerWithDecimalPlaces(99.6, 2));
+ Assert.IsTrue(100.0.IsLargerWithDecimalPlaces(99.4, 2));
- Assert.IsFalse(100.0.IsLargerWithDecimalPlaces(106.00, 2));
- Assert.IsTrue(100.0.IsLargerWithDecimalPlaces(94.000, 2));
-
- var max = 4 * Math.Pow(10, _doublePrecision.Magnitude());
+ var max = 0.4 * Math.Pow(10, _doublePrecision.Magnitude());
Assert.IsFalse(0.0.IsLargerWithDecimalPlaces(max, -_doublePrecision.Magnitude()));
Assert.IsFalse(0.0.IsLargerWithDecimalPlaces(-max, -_doublePrecision.Magnitude()));
- max = 6 * Math.Pow(10, _doublePrecision.Magnitude());
+ max = 0.6 * Math.Pow(10, _doublePrecision.Magnitude());
Assert.IsFalse(0.0.IsLargerWithDecimalPlaces(max, -_doublePrecision.Magnitude()));
Assert.IsTrue(0.0.IsLargerWithDecimalPlaces(-max, -_doublePrecision.Magnitude()));
}
@@ -934,23 +1037,21 @@ namespace MathNet.Numerics.UnitTests
Assert.IsFalse(double.PositiveInfinity.IsSmallerWithDecimalPlaces(double.PositiveInfinity, 2));
Assert.IsFalse(double.NegativeInfinity.IsSmallerWithDecimalPlaces(double.NegativeInfinity, 2));
- Assert.IsFalse(1.0.IsSmallerWithDecimalPlaces(1.04, 2));
- Assert.IsFalse(1.0.IsSmallerWithDecimalPlaces(0.96, 2));
-
- Assert.IsTrue(1.0.IsSmallerWithDecimalPlaces(1.06, 2));
- Assert.IsFalse(1.0.IsSmallerWithDecimalPlaces(0.94, 2));
-
- Assert.IsFalse(100.0.IsSmallerWithDecimalPlaces(104.00, 2));
- Assert.IsFalse(100.0.IsSmallerWithDecimalPlaces(96.000, 2));
+ Assert.IsTrue(1.0.IsSmallerWithDecimalPlaces(1.006, 2));
+ Assert.IsFalse(1.0.IsSmallerWithDecimalPlaces(1.004, 2));
+ Assert.IsFalse(1.0.IsSmallerWithDecimalPlaces(0.996, 2));
+ Assert.IsFalse(1.0.IsSmallerWithDecimalPlaces(0.994, 2));
- Assert.IsTrue(100.0.IsSmallerWithDecimalPlaces(106.00, 2));
- Assert.IsFalse(100.0.IsSmallerWithDecimalPlaces(94.000, 2));
+ Assert.IsTrue(100.0.IsSmallerWithDecimalPlaces(100.6, 2));
+ Assert.IsFalse(100.0.IsSmallerWithDecimalPlaces(100.4, 2));
+ Assert.IsFalse(100.0.IsSmallerWithDecimalPlaces(99.6, 2));
+ Assert.IsFalse(100.0.IsSmallerWithDecimalPlaces(99.4, 2));
- var max = 4 * Math.Pow(10, _doublePrecision.Magnitude());
+ var max = 0.4 * Math.Pow(10, _doublePrecision.Magnitude());
Assert.IsFalse(0.0.IsSmallerWithDecimalPlaces(max, -_doublePrecision.Magnitude()));
Assert.IsFalse(0.0.IsSmallerWithDecimalPlaces(-max, -_doublePrecision.Magnitude()));
- max = 6 * Math.Pow(10, _doublePrecision.Magnitude());
+ max = 0.6 * Math.Pow(10, _doublePrecision.Magnitude());
Assert.IsTrue(0.0.IsSmallerWithDecimalPlaces(max, -_doublePrecision.Magnitude()));
Assert.IsFalse(0.0.IsSmallerWithDecimalPlaces(-max, -_doublePrecision.Magnitude()));
}
@@ -1084,22 +1185,22 @@ namespace MathNet.Numerics.UnitTests
Assert.AreEqual(0, Precision.CompareToInDecimalPlaces(0, -0, Precision.NumberOfDecimalPlacesForFloats));
// compare two nearby numbers
- Assert.AreEqual(-1, 1.0.CompareToInDecimalPlaces(1.0 + (10 * _doublePrecision), Precision.NumberOfDecimalPlacesForDoubles));
+ Assert.AreEqual(-1, 1.0.CompareToInDecimalPlaces(1.0 + 10*_doublePrecision, Precision.NumberOfDecimalPlacesForDoubles));
Assert.AreEqual(0, 1.0.CompareToInDecimalPlaces(1.0 + _doublePrecision, Precision.NumberOfDecimalPlacesForDoubles));
Assert.AreEqual(0, 1.0.CompareToInDecimalPlaces(1.0 - _doublePrecision, Precision.NumberOfDecimalPlacesForDoubles));
- Assert.AreEqual(1, 1.0.CompareToInDecimalPlaces(1.0 - (10 * _doublePrecision), Precision.NumberOfDecimalPlacesForDoubles));
+ Assert.AreEqual(1, 1.0.CompareToInDecimalPlaces(1.0 - 10*_doublePrecision, Precision.NumberOfDecimalPlacesForDoubles));
// compare with the two numbers reversed in compare order
- Assert.AreEqual(1, (1.0 + (10 * _doublePrecision)).CompareToInDecimalPlaces(1.0, Precision.NumberOfDecimalPlacesForDoubles));
+ Assert.AreEqual(1, (1.0 + 10*_doublePrecision).CompareToInDecimalPlaces(1.0, Precision.NumberOfDecimalPlacesForDoubles));
Assert.AreEqual(0, (1.0 + _doublePrecision).CompareToInDecimalPlaces(1.0, Precision.NumberOfDecimalPlacesForDoubles));
Assert.AreEqual(0, (1.0 - _doublePrecision).CompareToInDecimalPlaces(1.0, Precision.NumberOfDecimalPlacesForDoubles));
- Assert.AreEqual(-1, (1.0 - (10 * _doublePrecision)).CompareToInDecimalPlaces(1.0, Precision.NumberOfDecimalPlacesForDoubles));
+ Assert.AreEqual(-1, (1.0 - 10*_doublePrecision).CompareToInDecimalPlaces(1.0, Precision.NumberOfDecimalPlacesForDoubles));
// compare two slightly more different numbers
- Assert.AreEqual(-1, 1.0.CompareToInDecimalPlaces(1.0 + (50 * _doublePrecision), Precision.NumberOfDecimalPlacesForDoubles));
- Assert.AreEqual(0, 1.0.CompareToInDecimalPlaces(1.0 + (50 * _doublePrecision), Precision.NumberOfDecimalPlacesForDoubles - 2));
- Assert.AreEqual(0, 1.0.CompareToInDecimalPlaces(1.0 - (50 * _doublePrecision), Precision.NumberOfDecimalPlacesForDoubles - 2));
- Assert.AreEqual(1, 1.0.CompareToInDecimalPlaces(1.0 - (50 * _doublePrecision), Precision.NumberOfDecimalPlacesForDoubles));
+ Assert.AreEqual(-1, 1.0.CompareToInDecimalPlaces(1.0 + (50*_doublePrecision), Precision.NumberOfDecimalPlacesForDoubles));
+ Assert.AreEqual(0, 1.0.CompareToInDecimalPlaces(1.0 + (50*_doublePrecision), Precision.NumberOfDecimalPlacesForDoubles - 2));
+ Assert.AreEqual(0, 1.0.CompareToInDecimalPlaces(1.0 - (50*_doublePrecision), Precision.NumberOfDecimalPlacesForDoubles - 2));
+ Assert.AreEqual(1, 1.0.CompareToInDecimalPlaces(1.0 - (50*_doublePrecision), Precision.NumberOfDecimalPlacesForDoubles));
// compare different numbers
Assert.AreEqual(1, 2.0.CompareToInDecimalPlaces(1.0, Precision.NumberOfDecimalPlacesForDoubles));