1,105,197 Community Members

Math Helpers

Member Avatar
(lxXTaCoXxl)
Reputation Points: 11 [?]
Q&As Helped to Solve: 18 [?]
Skill Endorsements: 4 [?]
 
0
 

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;
        }
    }
Member Avatar
lxXTaCoXxl
Posting Whiz
314 posts since Mar 2011
Reputation Points: 11 [?]
Q&As Helped to Solve: 18 [?]
Skill Endorsements: 4 [?]
 
0
 

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)));
}
Member Avatar
Ab000dy_85
Junior Poster in Training
69 posts since Dec 2007
Reputation Points: -3 [?]
Q&As Helped to Solve: 8 [?]
Skill Endorsements: 0 [?]
 
0
 

Yea GetDistance is very useful,

I had a project where I used this alot,

this is usful when using 2D or more

Member Avatar
deceptikon
Eternally Awesome
4,671 posts since Jan 2012
Reputation Points: 1,341 [?]
Q&As Helped to Solve: 680 [?]
Skill Endorsements: 104 [?]
Administrator
Featured
 
1
 

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

Member Avatar
lxXTaCoXxl
Posting Whiz
314 posts since Mar 2011
Reputation Points: 11 [?]
Q&As Helped to Solve: 18 [?]
Skill Endorsements: 4 [?]
 
0
 

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.

Member Avatar
lxXTaCoXxl
Posting Whiz
314 posts since Mar 2011
Reputation Points: 11 [?]
Q&As Helped to Solve: 18 [?]
Skill Endorsements: 4 [?]
 
0
 

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.

Member Avatar
ddanbe
Posting Expert
5,336 posts since Oct 2008
Reputation Points: 2,054 [?]
Q&As Helped to Solve: 904 [?]
Skill Endorsements: 46 [?]
Featured
 
0
 

While you are at it, what about reciprocal?

Member Avatar
lxXTaCoXxl
Posting Whiz
314 posts since Mar 2011
Reputation Points: 11 [?]
Q&As Helped to Solve: 18 [?]
Skill Endorsements: 4 [?]
 
0
 

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

Member Avatar
lxXTaCoXxl
Posting Whiz
314 posts since Mar 2011
Reputation Points: 11 [?]
Q&As Helped to Solve: 18 [?]
Skill Endorsements: 4 [?]
 
0
 

@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. :)

Member Avatar
skatamatic
Posting Shark
980 posts since Nov 2007
Reputation Points: 371 [?]
Q&As Helped to Solve: 133 [?]
Skill Endorsements: 5 [?]
 
1
 

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

Member Avatar
digitig
Newbie Poster
4 posts since Feb 2011
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
1
 

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.

Member Avatar
Momerath
Senior Poster
3,822 posts since Aug 2010
Reputation Points: 1,323 [?]
Q&As Helped to Solve: 661 [?]
Skill Endorsements: 19 [?]
Featured
 
0
 

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.

Member Avatar
nmaillet
Posting Pro
535 posts since Aug 2008
Reputation Points: 97 [?]
Q&As Helped to Solve: 106 [?]
Skill Endorsements: 7 [?]
 
0
 

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; }
Member Avatar
skatamatic
Posting Shark
980 posts since Nov 2007
Reputation Points: 371 [?]
Q&As Helped to Solve: 133 [?]
Skill Endorsements: 5 [?]
 
1
 

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

You
Post:
Start New Discussion
Tags Related to this Article