Math Helpers

lxXTaCoXxl 0 Tallied Votes 158 Views Share

Just a couple basic static mathematical helper methods that I've found useful for game development. Feel free to add some in replies for future visitors. I will do another post later this week with advanced helper methods from trig and calc. I will also do a geometry helper class as well.

public class MathHelper {
        public static float AbsoluteValue(float Value) {
            if (Value < 0)
                Value *= -1;

            return Value;
        }

        public static float Hold(float Value, float Minimum, float Maximum) {
            if (Value < Minimum)
                Value = Minimum;

            if (Value > Maximum)
                Value = Maximum;

            return Value;
        }

        public static float ToPower(float Base, int Exponent) {
            float b = Base;

            if (Exponent == 0) { b = 1; }

            else if (Exponent > 0) {
                for (int i = 0; i < Exponent; i++)
                    Base *= b;
            }

            else if (Exponent < 0) {
                Exponent *= -1;

                for (int i = 1; i < Exponent; i++)
                    Base *= b;

                Base = 1 / Base;
            }

            return Base;
        }

        public static float SquareRoot(float Value) {
            if (Value == 0) { return 0; }

            float v = (Value / 2) + 1;
            float v1 = (v + (Value / 2)) / 2;

            while (v1 < v) {
                v = v1;
                v1 = (v + (Value / v)) / 2;
            }

            return v;
        }

        public static float[] QuadraticFormula(float a, float b, float c) {
	        Complex ca = new Complex(a, 0);
	        Complex cb = new Complex(b, 0);
	        Complex cc = new Complex(c, 0);

        	Complex Δ = (cb * cb) - (4 * ca * cc);
    	    Complex r1 = (-cb + Complex.Sqrt(Δ) / (2 * ca));
        	Complex r2 = (-cb - Complex.Sqrt(Δ) / (2 * ca));
	
    	    float[] r = new float[2];

            if (r1.Imaginary == 0 && r2.Imaginary == 0)
	            r = new float[]{Convert.ToSingle(r1.Real), Convert.ToSingle(r2.Real)};

            else if (r1.Imaginary == 0)
	            r = new float[]{Convert.ToSingle(r1.Real), Convert.ToSingle(r2.Imaginary)};

            else if (r2.Imaginary == 0)
	            r = new float[]{Convert.ToSingle(r1.Imaginary), Convert.ToSingle(r2.Real)};

            else
	            r = new float[]{Convert.ToSingle(r1.Imaginary), Convert.ToSingle(r2.Imaginary)};

	        return r;
        }

        public static float Square(float Value) { return Value * Value; }
        public static float Cube(float Value) { return Square(Value) * Value; }

        public static float CubedSquared_Added(float Value) { return Cube(Value) + Square(Value); }
        public static float CubedSquared_Subtracted(float Value) { return Cube(Value) - Square(Value); }
        public static float CubedSquared_Multiplied(float Value) { return Cube(Value) * Square(Value); }
        public static float CubedSquared_Divided(float Value) { return Cube(Value) / Square(Value); }

        public static float LowerValue(float Value1, float Value2) {
            return Value1 < Value2 ? Value1 : Value2;
        }

        public static float GreaterValue(float Value1, float Value2) {
            return Value1 > Value2 ? Value1 : Value2;
        }

        public static float PercentIncrease(float OriginalValue, float NewValue) {
            return ((NewValue - OriginalValue) / OriginalValue) * 100;
        }

        public static float PercentDecrease(float OriginalValue, float NewValue) {
            return ((OriginalValue - NewValue) / OriginalValue) * 100;
        }
    }
lxXTaCoXxl 26 Posting Whiz in Training

Another useful one that I just thought I'd share is the distance between two points. Requires two 2 dimensional vector variables (Point, Vector2, etc) in order to work. This method uses the Square method included above.

public static float GetDistance(Point Point1, Point Point2) {
	return SquareRoot(Square((Point2.X - Point1.X)) + Square((Point2.Y - Point1.Y)));
}
Ab000dy_85 -3 Junior Poster in Training

Yea GetDistance is very useful,

I had a project where I used this alot,

this is usful when using 2D or more

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Some of those overlap with the standard C# library, what's the benefit of using your versions?

lxXTaCoXxl 26 Posting Whiz in Training

There is no benefit from using my versions, but some beginners don't exactly know about the Math class in C#, also others can study the algorithms or return methods or even just the logic to see different programming styles, understand how a specific formula works completely, and other means of being useful.

On another note, I've re-written the SquareRoot method to accept different roots other than two. Special thanks to Momerath for pointing out issues with the original algorithm.

// Uses the ToPower method, and the AbsoluteValue methods provided above.
        public static float NthRoot(float Base, int Index) {
            float Δ = Index;
            float Ω = Base / Δ;

            while (AbsoluteValue(Base - ToPower(Ω, (int)Δ)) > 0.00001f) {
                Ω = (1.0f / Δ) * ((Δ - 1) * Ω + (Base / ToPower(Ω, (int)(Index - 1))));
            }

            return Ω;
        }

Another couple re-writes and useful methods are:

/// <summary>
        /// Wrap an angle between π and -π.
        /// </summary>
        /// <param name="Value">The value to wrap.</param>
        /// <returns>The wrapped value between π and -π.</returns>
        public static float Wrap(float Value) {
            while (Value < MathConstants.π)
                Value += MathConstants.π2;

            while (Value > MathConstants.π)
                Value -= MathConstants.π2;

            return Value;
        }

        /// <summary>
        /// Returns the absolute value of a floating point value.
        /// </summary>
        /// <param name="Value">A floating point number representing the value to test.</param>
        /// <returns>The absolute value of the value given.</returns>
        public static float AbsoluteValue(float Value) {
            return Value > 0 ? Value : Value * -1;
        }

        /// <summary>
        /// Holds a specified value between a minimum and maximum value.
        /// </summary>
        /// <param name="Value">The value to hold.</param>
        /// <param name="Minimum">The minimum value.</param>
        /// <param name="Maximum">The maximum value.</param>
        /// <returns>The held value between the minimum and maximum.</returns>
        public static float Hold(float Value, float Minimum, float Maximum) {
            Value = Value < Minimum ? Minimum : Value;
            Value = Value > Maximum ? Maximum : Value;
            return Value;
        }

    public class MathConstants {
        /// <summary>
        /// The numerical value of the Pi constant down to the 20th decimal place.
        /// </summary>
        public const float π = 3.1415926535897932384f;

        /// <summary>
        /// Two times Pi.
        /// </summary>
        public const float π2 = π * 2;

        /// <summary>
        /// Pi divided by 2.
        /// </summary>
        public const float πOver2 = π / 2;

        /// <summary>
        /// Pi divided by 4.
        /// </summary>
        public const float πOver4 = π / 4;

        /// <summary>
        /// The Golden Ratio, approx: 1.61803398874.
        /// </summary>
        public const float φ = (1 + MathHelper.NthRoot(5, 2)) / 2;

        /// <summary>
        /// The Omega constant, approx: 0.5671432904.
        /// </summary>
        public const float Ω = 0.5671432904f;
    }

Will be posting some physics formulas that are useful in game development later this week.

lxXTaCoXxl 26 Posting Whiz in Training

The following line needs to be converted over to the second line if anyone is using it.

public const float φ = (1 + MathHelper.NthRoot(5, 2)) / 2;
public const float φ = 1.61803398874;

Because you can't call methods apparently while assigning values to constants.

Anyways, I haven't had time to post anymore useful snippets, but I do have an archive on my laptop. This is a public computer so I don't have access to it right now. As soon as I get back to my place next week I'll post them.

ddanbe 2,724 Professional Procrastinator Featured Poster

While you are at it, what about reciprocal?

lxXTaCoXxl 26 Posting Whiz in Training

Good Idea; I'll generate an algorithm for that too. :)

lxXTaCoXxl 26 Posting Whiz in Training

@ddanbe Which would you perfer to see as an algorithim? I mean I can do them all but, if you had to choose one. :)

Multiplicative Inverse (Also known as Reciprocal)
Reciprocal of a Spiral
Reciprocal of a Polynomial

Sorry it took so long to get back to work on this, I got caught up in requested work. :)

skatamatic 371 Practically a Posting Shark

Ummm. Aren't all of those the same thing? (1 / input)

digitig 0 Newbie Poster

There are good reasons for not using these functions. They're fine as a learning excercise for the original poster, but they're nowhere near production quality. QuadraticFomula crashes if a is zero, AbsoluteValue has an unneccesary multiplication (which the optimizer might replace) and involves unnecessary coercions if called with anything but a float. NthRoot is an inefficient way of doing what Math.Pow could do for itself (and crashes for Index==0), the SquareRoot algorithm is inefficient, and so on. The solution to beginners not knowing about the Math class in C# is to point them to the Math class, not to reinvent an inferior version.

Momerath 1,327 Nearly a Senior Poster Featured Poster

QuadraticFomula crashes if a is zero,

It's not a quadratic equation if a is zero :) I do agree, though, that some error checking needs to be included.

nmaillet 97 Posting Whiz in Training

There are good reasons for not using these functions. They're fine as a learning excercise for the original poster, but they're nowhere near production quality. QuadraticFomula crashes if a is zero, AbsoluteValue has an unneccesary multiplication (which the optimizer might replace) and involves unnecessary coercions if called with anything but a float. NthRoot is an inefficient way of doing what Math.Pow could do for itself (and crashes for Index==0), the SquareRoot algorithm is inefficient, and so on. The solution to beginners not knowing about the Math class in C# is to point them to the Math class, not to reinvent an inferior version.

I agree. Another thing I would like to point out, there are far too many unnecessary function calls. For instance:

public static float Square(float Value) { return Value * Value; }
public static float Cube(float Value) { return Square(Value) * Value; }

Is it really necessary to add the extra overhead of a function call when you could simply write Value * Value * Value? I do realize that the compiler will likely, with optimizations enabled, remove these calls, but when the term game development is used, it makes me think of an attempt at efficiency. While I'm on this though, I think the worst offender is:

public static float CubedSquared_Divided(float Value) { return Cube(Value) / Square(Value); }

That is 3 function calls, 1 division and some multiplication operations that could simply be replaced with:

public static float CubedSquared_Divided(float Value) { return Value; }
skatamatic 371 Practically a Posting Shark

I'm thinking this whole post was to show us how cool pi theta and delta characters look.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.