Tests whether two float/double values are equal, within an acceptable margin of difference.
namespace NMA.Infrastructure.Builders { #region Usings using System; #endregion /// <summary> /// Miscellaneous math utility methods. /// </summary> /// <remarks>Please be careful in your use of the methods that take left, /// right and epsilon. Because of the imprecise nature of floating point /// calculations, the comparison of <i>epsilon</i> to the difference between /// <i>left</i> and <i>right</i> is not guaranteed to be precise. For example, /// if left is 90.0001, right is 90.0000 and epsilon is 0.0001, this method /// might not necessarily return true. I have seen these values produce a /// diffence of 0.00010000000000332, which is actually greater than 0.0001. /// You must take this fuzzyness into account in your client classes and /// unit tests. This is precisely why we have these epsilon methods in the /// first place! /// </remarks> public class MathUtil { /// <summary> /// Tests whether two float values are equal, within an acceptable margin /// of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if the values are equal, within <i>epsilon</i>; otherwise, false</returns> /// <see cref="float.Equals"/> /// <see href="http://stackoverflow.com/questions/485175"/> /// <see href="http://www.brainbell.com/tutorials/C++/Comparing_Floating-Point_Numbers_With_Bounded_Accuracy.htm"/> public static bool FloatEqualTo(float left, float right, float epsilon) { return Math.Abs(left - right) <= epsilon; } /// <summary> /// Tests whether a float value is greater than another float value, /// within an acceptable margin of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if <i>left</i> is greater than <i>right</i>, within <i>epsilon</i>; otherwise, false</returns> public static bool FloatGreaterThan(float left, float right, float epsilon) { // delegate return FloatGreaterThan(left, right, epsilon, false); } /// <summary> /// Tests whether a float value is greater than or equal to another float /// value, within an acceptable margin of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if <i>left</i> is greater than or equal to <i>right</i>, within <i>epsilon</i>; otherwise, false</returns> public static bool FloatGreaterThanOrEqualTo(float left, float right, float epsilon) { // delegate return FloatGreaterThan(left, right, epsilon, true); } // impl private static bool FloatGreaterThan(float left, float right, float epsilon, bool orEqualTo) { if (FloatEqualTo(left, right, epsilon)) { // within epsilon, so considered equal return orEqualTo; } return left > right; } /// <summary> /// Tests whether a float value is less than another float value, /// within an acceptable margin of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if <i>left</i> is less than <i>right</i>, within <i>epsilon</i>; otherwise, false</returns> public static bool FloatLessThan(float left, float right, float epsilon) { // delegate return FloatLessThan(left, right, epsilon, false); } /// <summary> /// Tests whether a float value is less than or equal to another float value, /// within an acceptable margin of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if <i>left</i> is less than or equal to<i>right</i>, within <i>epsilon</i>; otherwise, false</returns> public static bool FloatLessThanOrEqualTo(float left, float right, float epsilon) { // delegate return FloatLessThan(left, right, epsilon, true); } // impl private static bool FloatLessThan(float left, float right, float epsilon, bool orEqualTo) { if (FloatEqualTo(left, right, epsilon)) { // within epsilon, so considered equal return orEqualTo; } return left < right; } /// <summary> /// Tests whether two double values are equal, within an acceptable margin /// of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if the values are equal, within <i>epsilon</i>; otherwise, false</returns> /// <see cref="double.Equals"/> public static bool DoubleEqualTo(double left, double right, double epsilon) { return Math.Abs(left - right) <= epsilon; } /// <summary> /// Tests whether a double value is greater than another double value, /// within an acceptable margin of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if <i>left</i> is greater than <i>right</i>, within <i>epsilon</i>; otherwise, false</returns> public static bool DoubleGreaterThan(double left, double right, double epsilon) { // delegate return DoubleGreaterThan(left, right, epsilon, false); } /// <summary> /// Tests whether a double value is greater than or equal to another double /// value, within an acceptable margin of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if <i>left</i> is greater than or equal to <i>right</i>, within <i>epsilon</i>; otherwise, false</returns> public static bool DoubleGreaterThanOrEqualTo(double left, double right, double epsilon) { // delegate return DoubleGreaterThan(left, right, epsilon, true); } // impl private static bool DoubleGreaterThan(double left, double right, double epsilon, bool orEqualTo) { if (DoubleEqualTo(left, right, epsilon)) { // within epsilon, so considered equal return orEqualTo; } return left > right; } /// <summary> /// Tests whether a double value is less than another double value, /// within an acceptable margin of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if <i>left</i> is less than <i>right</i>, within <i>epsilon</i>; otherwise, false</returns> public static bool DoubleLessThan(double left, double right, double epsilon) { // delegate return DoubleLessThan(left, right, epsilon, false); } /// <summary> /// Tests whether a double value is less than or equal to another double /// value, within an acceptable margin of difference. /// </summary> /// <param name="left">the left side of the comparison</param> /// <param name="right">the right side of the comparison</param> /// <param name="epsilon">the margin of difference</param> /// <returns>true if <i>left</i> is less than or equal to <i>right</i>, within <i>epsilon</i>; otherwise, false</returns> public static bool DoubleLessThanOrEqualTo(double left, double right, double epsilon) { // delegate return DoubleLessThan(left, right, epsilon, true); } // impl private static bool DoubleLessThan(double left, double right, double epsilon, bool orEqualTo) { if (DoubleEqualTo(left, right, epsilon)) { // within epsilon, so considered equal return orEqualTo; } return left < right; } } }