Ranged numbers

This is a discussion on Ranged numbers within the Game Programming forums, part of the General Programming Boards category; Hey ! I was bored and I had this idea so here it is. It's a simple class containing a ...

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    903

    Ranged numbers

    Hey ! I was bored and I had this idea so here it is. It's a simple class containing a Data field and a Min and Max field where Data will be a number between Min and Max. Why is this in game programming ? Well, you can use this to contain the health, mana or whatever you wish. I've overloaded most operators though I can't see to make the pre and post-increment operators work. A problem of syntax, perhaps someone can help.

    PS: I know it may be a little bit of overhead but I think it cleans up a little of the mess in your code since you don't have to check boundaries and such.

    Code:
    #ifndef RANGED_NUM_H_INCLUDED
    #define RANGED_NUM_H_INCLUDED
    
    
    #define READJUST_VALUE(a, min, max) if(a < min) a = min; if(a > max) a = max
    
    
    template <typename T> 
    class RangedNum {
    public:
    
    	explicit RangedNum(T dat = 0, T min = 0, T max = 0) : Data(dat), Min(min), Max(max)
    	{
    
    	}
    
    	explicit RangedNum(const RangedNum<T>& cpy)
    	{
    		Data = cpy.Data;
    		Min = cpy.Min;
    		Max = cpy.Max;
    	}
    
    	void SetMinimum(T min = 0)
    	{
    		Min = min;
    		if(Min > Max) Min = Max;
    		READJUST_VALUE(Data, Min, Max);
    	}
    
    	void SetMaximum(T max = 0) 
    	{
    		Max = max;
    		if(Max < Min) Max = Min;
    		READJUST_VALUE(Data, Min, Max);
    	}
    
    	void SetRanges(T min, T max)
    	{
    		Min = min;
    		Max = max;
    		if(Min > Max) Min = Max;
    		READJUST_VALUE(Data, Min, Max);
    	}
    
    	operator T ()
    	{
    		return Data;
    	}
    
    	template <typename OpT>
    	T& operator + (const OpT& arg)
    	{
    		Tmp = Data + Arg;
    		READJUST_VALUE(Tmp, Min, Max);
    		return Tmp;
    	}
    
    	template <typename OpT>
    	T& operator += (const OpT& arg)
    	{
    		Data += arg;
    		READJUST_VALUE(Data, Min, Max);
    		return Data;
    	}
    
    	template <typename OpT>
    	T& operator - (const OpT& arg)
    	{
    		Tmp = Data - Arg;
    		READJUST_VALUE(Tmp, Min, Max);
    		return Tmp;
    	}
    
    	template <typename OpT>
    	T& operator -= (const OpT& arg)
    	{
    		Data -= arg;
    		READJUST_VALUE(Data, Min, Max);
    		return Data;
    	}
    
    	template <typename OpT>
    	T& operator * (const OpT& arg)
    	{
    		Tmp = Data * Arg;
    		READJUST_VALUE(Tmp, Min, Max);
    		return Tmp;
    	}
    
    	template <typename OpT>
    	T& operator *= (const OpT& arg)
    	{
    		Data *= arg;
    		READJUST_VALUE(Data, Min, Max);
    		return Data;
    	}
    
    	template <typename OpT>
    	T& operator / (const OpT& arg)
    	{
    		if(arg = 0) arg = 1;
    		Tmp = Data / Arg;
    		READJUST_VALUE(Tmp, Min, Max);
    		return Tmp;
    	}
    
    	template <typename OpT>
    	T& operator /= (const OpT& arg)
    	{
    		if(arg = 0) arg = 1;
    		Data /= arg;
    		READJUST_VALUE(Data, Min, Max);
    		return Data;
    	}
    
    	T& operator ++(RangedNum<T>& arg)
    	{
    		arg.Data++;
    		return arg.Data;
    	}
    
    	T& operator ++ ()
    	{
    		Data++;
    		return Data;
    	}
    
    	template <typename OpT>
    	bool operator == (const OpT& arg) const
    	{
    		return (Data == arg);
    	}
    
    	template <typename OpT>
    	bool operator != (const OpT& arg) const
    	{
    		return (Data != arg);
    	}
    
    protected:
    
    	T Data, Min, Max, Tmp;
    };
    
    
    #endif // RANGED_NUM_H_INCLUDED
    Last edited by Desolation; 07-24-2006 at 05:13 PM.

  2. #2
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    You are using nice features like templates and operator overloading, but at the same time you're using macros.

    To make the ++ operator work, use an unnamed int argument to distinguish pre- and post-increment. I'm sure you can google somthing.
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  3. #3
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,069
    As Sang-drax was saying, the prefix takes no operators, the postfix takes a dummy int operator. It's used for nothing, it's just there to tell the compiler that this is the postfix version.
    Sent from my iPad®

  4. #4
    Registered User
    Join Date
    May 2006
    Posts
    903
    Ok thank you for the info =]

    As for using macros, they are perfectly fine if you make a good use of them. Besides, my macro should read
    Code:
    #define READJUST_VALUE(a, min, max) if((a) < (min)) (a) = (min); if((a) > (max)) (a) = (max)
    and not
    Code:
    #define READJUST_VALUE(a, min, max) if(a < min) a = min; if(a > max) a = max

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,434
    And how is that possibly a good use of a macro??

    Nice class though.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,069
    That's real nice, now what happens if that macro is used in a conditional statement, loop statement, or function? Don't design bad code because you know the limited ways it could be used properly. Write good code and then you don't have to worry about whether or not you can use it where you're using it.
    Sent from my iPad®

  7. #7
    Registered User
    Join Date
    May 2006
    Posts
    903
    Gneh, for you ladies ;-)
    Code:
    template <typename T>
    inline T& ReadjustValues(T* a, T min, T max)
    {
      if((*a) < min) *a = min;
      if((*a) > max) *a = max;
      return *a;
    }
    PS: Just kidding by the way ;-)
    Last edited by Desolation; 07-25-2006 at 09:27 PM.

  8. #8
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,069
    Would you mind capitalizing the 'a' on adjust in your function name? I see that as "read just values".
    Sent from my iPad®

  9. #9
    Registered User
    Join Date
    May 2006
    Posts
    903
    I tried to add a little system to catch the difference between a and min or a and max in case of an overflow/underflow but I get a "OverflowException<T> cannot be raised" error (and the same for UnderflowException), what does that mean ?

    Code:
    template <typename T> 
    inline T& ReAdjustValues(T* a, T min, T max)  throw()
    { 
    	if((*a) < min)
    	{
    		*a = min;
    		throw (UnderflowException<T>(*a - min));
    	}
    	if((*a) > max)
    	{
    		*a = max;
    		throw (OverflowException<T>(*a - max));
    	}
    	return *a; 
    }
    
    
    template <typename T>
    class LimitBreakException
    {
    protected:
    
    	enum ExceptionType 
    	{
    		LBE_OVERFLOW, 
    		LBE_UNDERFLOW 
    	};
    
    public:
    
    	LimitBreakException(const T& diff) : Difference(diff)
    	{
    
    	}
    
    	virtual ~LimitBreakException() = 0;
    
    	const T& GetDifference() const
    	{
    		return Difference;
    	}
    
    	const ExceptionType& GetExceptionType() const
    	{
    		return EType;
    	}
    
    	const char* GetErrStr()
    	{
    		ErrStr.clear();
    		ErrStr << ((EType == LBE_OVERFLOW) ? "Overflow" : "Underflow");
    		ErrStr << " error by " << Difference;
    		return ErrStr.str().c_str();
    	}
    
    protected:
    
    	ExceptionType EType;
    	T Difference;
    
    private:
    
    	std::stringstream ErrStr;
    };
    
    
    template <typename T>
    class UnderflowException : public LimitBreakException<T>
    {
    public:
    
    	UnderflowException(const T& diff) : LimitBreakException<T>(diff), EType(LBE_UNDERFLOW)
    	{
    
    	}
    
    	~UnderflowException()
    	{
    
    	}
    
    };
    
    
    template <typename T>
    class OverflowException : public LimitBreakException<T>
    {
    public:
    
    	OverflowException(const T& diff) : LimitBreakException<T>(diff), EType(LBE_OVERFLOW)
    	{
    
    	}
    
    	~OverflowException()
    	{
    
    	}
    
    };
    PS: Yes, I didn't really notice that, I typed too fast I think =/

    PS: I did pre-declare the classes before using them, this is not the problem.
    Last edited by Desolation; 07-25-2006 at 10:08 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Question about random numbers
    By Kempelen in forum C Programming
    Replies: 2
    Last Post: 07-02-2008, 06:28 AM
  2. Logical errors with seach function
    By Taka in forum C Programming
    Replies: 4
    Last Post: 09-18-2006, 05:20 AM
  3. Generating ranged randomized numbers
    By Cloud_909 in forum C++ Programming
    Replies: 8
    Last Post: 12-05-2005, 04:42 PM
  4. the definition of a mathematical "average" or "mean"
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 12-03-2002, 10:15 AM
  5. A (complex) question on numbers
    By Unregistered in forum C++ Programming
    Replies: 8
    Last Post: 02-03-2002, 05:38 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21