Thursday, December 7, 2017

Asserting floating point values in unit tests


Just a few methods to help out with unit testing, mainly for asserting floating point values (float, double) to be within a tolerance of the expected value

public static class Dessert
{
    public static void AreEqual(double expected, double actual, double tolerance)
    {
        Assert.IsTrue(expected.IsEqual(actual, tolerance),
            $"{Environment.NewLine}Dessert.AreEqual(double, double) failed. Expected:<{expected}>. Actual<{actual}>. Tolerance<{tolerance}>");
    }
        
    public static void AreEqual(float expected, float actual, float tolerance)
    {
        Assert.IsTrue(expected.IsEqual(actual, tolerance),
            $"{Environment.NewLine}Dessert.AreEqual(float, float) failed. Expected:<{expected}>. Actual<{actual}>. Tolerance<{tolerance}>");
    }
}

How to use:

Dessert.AreEqual(2700, weight, 0.000000000000001);

All code provided as-is. This is copied from my own code-base, May need some additional programming to work. Use for whatever you want, how you want! If you find this helpful, please leave a comment, not required but appreciated! :)

Hope this helps someone out there!
Until next time, The power of compounding

Wednesday, November 15, 2017

Distances to human readable text in C#


Needed a function that converts a double to a human readable distance in my latest project, ended up writing the following function.
Input argument is in meters.
For values less than 1 meter, the result is given as centimeters.
For values up to 10 km, the values are given with one decimal.
Values up to one tenth of an Astronomical Unit are given as kilometers.
Values between one tenth of an Astronomical Unit and one tenth of a Parsec are given in Astronimical Units.
Values larger then one tenth of a Parsec are given in Parsecs.

Example output
Input
Output
0.533
53 cm
-1 -1 m
1 1 m
3,08568E+16 1.0 pc
3,08568E+17 10.0 pc
1,49598E+12 10.0 AU
1000 1.0 km
10000 10 km


The code for you to use as you please:
public const double AstronomicalUnit = 149597870700;
// https://en.wikipedia.org/wiki/Parsec
public static double Parsec { get; } = (648000 / Math.PI) * AstronomicalUnit;
public static string ToReadableDistanceFavorParsec(double meters, CultureInfo cultureInfo = null)
{
    if (cultureInfo == null)
        cultureInfo = CultureInfo.InvariantCulture;
    var sign = meters.Sign() > 0 ? string.Empty : "-";
    meters = meters.Abs();
    if (meters > (Parsec / 10))
    {
        return $"{sign}{(meters / Parsec).ToString("0.0", cultureInfo)} pc";
    }

    if (meters > (AstronomicalUnit / 10))
    {
        return $"{sign}{(meters / AstronomicalUnit).ToString("0.0", cultureInfo)} AU";
    }

    if (meters > (997))
    {

        if (meters >= (10000))
        {
            return $"{sign}{(meters / 1000).ToString("0", cultureInfo)} km";
        }
        return $"{sign}{(meters / 1000).ToString("0.0", cultureInfo)} km";
    }

    if (meters < 1)
    {
        return $"{sign}{meters * 100:0} cm";
    }
    return sign + meters.ToString("0") + " m";
}


All code provided as-is. This is copied from my own code-base, May need some additional programming to work. Use for whatever you want, how you want! If you find this helpful, please leave a comment, not required but appreciated! :)

Hope this helps someone out there!
Until next time, The power of compounding

Friday, October 13, 2017

System.Math extension methods

Why

Because I've lately started to think a little more functional, this also allows for nice chaining of calls to the Math class.

How to use

Say you want to calculate the angle between 2 vectors by taking arc cosine of our dot product to give us the angle:
With normal Math usage..
var dot = vector1.X* vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
double radians = Math.Acos(dot);
Same example with our extensions
var dot = vector1.X* vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z;
double radians = dot.Acos();

The above example but with a method to calculate the dot product.
double radians = vector1.Dot(vector2).Acos();


Code for your pleasure

public static class MathExtensions
{
    public static decimal Abs(this decimal d)
    {
        return Math.Abs(d);
    }
    public static float Abs(this float d)
    {
        return Math.Abs(d);
    }
    public static double Abs(this double d)
    {
        return Math.Abs(d);
    }
    public static int Abs(this int d)
    {
        return Math.Abs(d);
    }
    public static long Abs(this long d)
    {
        return Math.Abs(d);
    }
    public static short Abs(this short d)
    {
        return Math.Abs(d);
    }
    public static short Abs(this byte d)
    {
        return Math.Abs(d);
    }
    public static decimal Max(this decimal d, decimal x)
    {
        return Math.Max(d, x);
    }
    public static float Max(this float d, float x)
    {
        return Math.Max(d, x);
    }
    public static double Max(this double d, double x)
    {
        return Math.Max(d, x);
    }
    public static int Max(this int d, int x)
    {
        return Math.Max(d, x);
    }
    public static long Max(this long d, long x)
    {
        return Math.Max(d, x);
    }
    public static short Max(this short d, short x)
    {
        return Math.Max(d, x);
    }
    public static short Max(this byte d, byte x)
    {
        return Math.Max(d, x);
    }
    public static decimal Min(this decimal d, decimal x)
    {
        return Math.Min(d, x);
    }
    public static float Min(this float d, float x)
    {
        return Math.Min(d, x);
    }
    public static double Min(this double d, double x)
    {
        return Math.Min(d, x);
    }
    public static int Min(this int d, int x)
    {
        return Math.Min(d, x);
    }
    public static long Min(this long d, long x)
    {
        return Math.Min(d, x);
    }
    public static short Min(this short d, short x)
    {
        return Math.Min(d, x);
    }
    public static short Min(this byte d, byte x)
    {
        return Math.Min(d, x);
    }

    public static int Sign(this decimal d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this float d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this double d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this int d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this long d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this short d)
    {
        return Math.Sign(d);
    }
    public static int Sign(this byte d)
    {
        return Math.Sign(d);
    }
    public static decimal Floor(this decimal d)
    {
        return Math.Floor(d);
    }
    public static double Floor(this float d)
    {
        return Math.Floor(d);
    }
    public static double Floor(this double d)
    {
        return Math.Floor(d);
    }
    public static decimal Round(this decimal d)
    {
        return Math.Round(d);
    }
    public static decimal Round(this decimal d, int x)
    {
        return Math.Round(d, x);
    }
    public static decimal Round(this decimal d, int x, MidpointRounding mr)
    {
        return Math.Round(d, x, mr);
    }
    public static decimal Round(this decimal d, MidpointRounding mr)
    {
        return Math.Round(d, mr);
    }
    public static double Round(this float d)
    {
        return Math.Round(d);
    }
    public static double Round(this double d)
    {
        return Math.Round(d);
    }
    public static double Round(this double d, int x)
    {
        return Math.Round(d, x);
    }
    public static double Round(this double d, int x, MidpointRounding mr)
    {
        return Math.Round(d, x, mr);
    }
    public static double Round(this double d, MidpointRounding mr)
    {
        return Math.Round(d, mr);
    }
    public static decimal Ceiling(this decimal d)
    {
        return Math.Ceiling(d);
    }
    public static double Ceiling(this float d)
    {
        return Math.Ceiling(d);
    }
    public static double Ceiling(this double d)
    {
        return Math.Ceiling(d);
    }
    public static double Acos(this double d)
    {
        return Math.Acos(d);
    }
    public static double Asin(this double d)
    {
        return Math.Asin(d);
    }
    public static double Atan(this double d)
    {
        return Math.Atan(d);
    }
    public static double Atan2(this double d, double x)
    {
        return Math.Atan2(d, x);
    }
    public static double Cos(this double d)
    {
        return Math.Cos(d);
    }
    public static double Cosh(this double d)
    {
        return Math.Cosh(d);
    }
    public static double Exp(this double d)
    {
        return Math.Exp(d);
    }
    public static double Sin(this double d)
    {
        return Math.Sin(d);
    }
    public static double Sinh(this double d)
    {
        return Math.Sinh(d);
    }
    public static double Tan(this double d)
    {
        return Math.Tan(d);
    }
    public static double Tanh(this double d)
    {
        return Math.Tanh(d);
    }
    public static long BigMul(this int a, int b)
    {
        return Math.BigMul(a, b);
    }
    public static double IEEERemainder(this double d, double y)
    {
        return Math.IEEERemainder(d, y);
    }
    public static double Log(this double d)
    {
        return Math.Log(d);
    }
    public static double Log(this double d, double x)
    {
        return Math.Log(d, x);
    }
    public static double Log10(this double d)
    {
        return Math.Log10(d);
    }
    public static double Sqrt(this double d)
    {
        return Math.Sqrt(d);
    }
    public static decimal Truncate(this decimal d)
    {
        return Math.Truncate(d);
    }
    public static double Truncate(this double d)
    {
        return Math.Truncate(d);
    }
    public static double Pow(this double d, double power)
    {
        return Math.Pow(d, power);
    }
}

Quite a lot of overloads, I think I got them all but if you find that I've missed one, please comment on this post and I will add it!

All code provided as-is. This is copied from my own code-base, May need some additional programming to work. Use for whatever you want, how you want! If you find this helpful, please leave a comment, not required but appreciated! :)

Hope this helps someone out there!
Until next time, Defining your own life