|
using System;
namespace CodeProject.VisualStudio.QualityTools.UnitTestFramework
{
internal static class Numerics
{
#region Numeric Type Recognition
public static bool IsNumeric<T>()
{
return IsFixedPointNumeric<T>() || IsFloatingPointNumeric<T>();
}
public static bool IsFloatingPointNumeric<T>()
{
Type type = typeof(T);
return (type.Equals(typeof(double)) || type.Equals(typeof(float)));
}
public static bool IsFixedPointNumeric<T>()
{
Type type = typeof(T);
return (type.Equals(typeof(byte)) ||
type.Equals(typeof(sbyte)) ||
type.Equals(typeof(decimal)) ||
type.Equals(typeof(int)) ||
type.Equals(typeof(uint)) ||
type.Equals(typeof(long)) ||
type.Equals(typeof(ulong)) ||
type.Equals(typeof(short)) ||
type.Equals(typeof(ushort)));
}
#endregion
#region Numeric Equality
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToUInt64(System.Object)")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToUInt32(System.Object)")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt64(System.Object)")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToInt32(System.Object)")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToDouble(System.Object)")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Convert.ToDecimal(System.Object)")]
public static bool AreEqual<T1, T2, T3>(T1 expected, T2 actual, T3 tolerance)
{
if (IsFloatingPointNumeric<T1>() || IsFloatingPointNumeric<T2>())
return AreEqual(Convert.ToDouble(expected), Convert.ToDouble(actual), Convert.ToDouble(tolerance));
if (expected is decimal || actual is decimal)
return AreEqual(Convert.ToDecimal(expected), Convert.ToDecimal(actual), Convert.ToDecimal(tolerance));
if (expected is ulong || actual is ulong)
return AreEqual(Convert.ToUInt64(expected), Convert.ToUInt64(actual), Convert.ToUInt64(tolerance));
if (expected is long || actual is long)
return AreEqual(Convert.ToInt64(expected), Convert.ToInt64(actual), Convert.ToInt64(tolerance));
if (expected is uint || actual is uint)
return AreEqual(Convert.ToUInt32(expected), Convert.ToUInt32(actual), Convert.ToUInt32(tolerance));
return AreEqual(Convert.ToInt32(expected), Convert.ToInt32(actual), Convert.ToInt32(tolerance));
}
private static bool AreEqual(double expected, double actual, double tolerance)
{
if (double.IsNaN(expected) && double.IsNaN(actual))
return true;
// handle infinity specially since subtracting two infinite values gives
// NaN and the following test fails. mono also needs NaN to be handled
// specially although ms.net could use either method.
if (double.IsInfinity(expected) || double.IsNaN(expected) || double.IsNaN(actual))
return expected.Equals(actual);
if (tolerance > 0.0d)
return Math.Abs(expected - actual) <= tolerance;
return expected.Equals(actual);
}
private static bool AreEqual(decimal expected, decimal actual, decimal tolerance)
{
if (tolerance > 0m)
return Math.Abs(expected - actual) <= tolerance;
return expected.Equals(actual);
}
private static bool AreEqual(ulong expected, ulong actual, ulong tolerance)
{
if (tolerance > 0ul)
{
ulong diff = expected >= actual ? expected - actual : actual - expected;
return diff <= tolerance;
}
return expected.Equals(actual);
}
private static bool AreEqual(long expected, long actual, long tolerance)
{
if (tolerance > 0L)
return Math.Abs(expected - actual) <= tolerance;
return expected.Equals(actual);
}
private static bool AreEqual(uint expected, uint actual, uint tolerance)
{
if (tolerance > 0)
{
uint diff = expected >= actual ? expected - actual : actual - expected;
return diff <= tolerance;
}
return expected.Equals(actual);
}
private static bool AreEqual(int expected, int actual, int tolerance)
{
if (tolerance > 0)
return Math.Abs(expected - actual) <= tolerance;
return expected.Equals(actual);
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Windows developer with 10+ years experience working in the banking industry.