0

After having a lot of problems regarding to double type variables, problems like testing for equality and division by zero, I thought of making a class to handle double values and try to seamlessly switch the intrinsic doubles we use regularly with the new class. it doesn't fit completely though. here's my class:

class HDouble
{
  //private:
public:
  double dValue;
  static const double dEpsilon;


  HDouble()
  {
    dValue = 0.0;
  }

  HDouble(double OtherValue)
  {
    if (IsNaN(OtherValue))
    {
      assert(0);
    }
    dValue = OtherValue;
  }

  const HDouble& operator=(const HDouble& OtherValue)
  {
    if (this == &OtherValue)      // Same object?
      return *this;

    if (IsNaN(OtherValue.dValue))
    {
      assert(0);
    }
    dValue = OtherValue.dValue;
    return *this;
  }

  const HDouble& operator=(const double& OtherValue)
  {
    dValue = OtherValue;
    return *this;
  }
  bool operator==(const HDouble& OtherValue)
  {
    return (abs(dValue - OtherValue.dValue) < dEpsilon);
  }

  //////////////////////////////////////////////////////////////////////////
  const HDouble& operator++()
  {
    dValue++;
    return *this;
  }
  const HDouble& operator++(int dummy)
  {
    dValue++;
    return *this;
  }
  const HDouble& operator--()
  {
    dValue--;
    return *this;
  }
  const HDouble& operator--(int dummy)
  {
    dValue--;
    return *this;
  }


//////////////////////////////////////////////////////////////////////////
  HDouble operator*(const HDouble& OtherValue)
  {
    HDouble Result = *this;
    Result *= OtherValue;
    return Result;
  }
  HDouble operator*(const double& OtherValue)
  {
    HDouble Result = *this;
    Result *= OtherValue;
    return Result;
  }

  HDouble operator/(const HDouble& OtherValue)
  {
    HDouble Result = *this;
    Result /= OtherValue;
    return Result;
  }
  HDouble operator/(const double& OtherValue)
  {
    HDouble Result = *this;
    Result /= OtherValue;
    return Result;
  }

  HDouble operator+(const HDouble& OtherValue)
  {
    HDouble Result = *this;
    Result += OtherValue;
    return Result;
  }
  HDouble operator+(const double& OtherValue)
  {
    HDouble Result = *this;
    Result += OtherValue;
    return Result;
  }

  HDouble operator-(const HDouble& OtherValue)
  {
    HDouble Result = *this;
    Result -= OtherValue;
    return Result;
  }
  HDouble operator-(const double& OtherValue)
  {
    HDouble Result = *this;
    Result -= OtherValue;
    return Result;
  }

  //////////////////////////////////////////////////////////////////////////
  HDouble& operator*=(const double& OtherValue)
  {
    dValue *= OtherValue;
    return *this;
  }
  HDouble& operator*=(const HDouble& OtherValue)
  {
    dValue *= OtherValue.dValue;
    return *this;
  }

  HDouble& operator+=(const HDouble& OtherValue)
  {
    dValue += OtherValue.dValue;
    return *this;
  }
  HDouble& operator+=(const double& OtherValue)
  {
    dValue += OtherValue;
    return *this;
  }


  HDouble& operator-=(const double& OtherValue)
  {
    dValue -= OtherValue;
    return *this;
  }
  HDouble& operator-=(const HDouble& OtherValue)
  {
    dValue -= OtherValue.dValue;
    return *this;
  }

  HDouble& operator/=(const double& OtherValue)
  {
    dValue /= OtherValue;
    return *this;
  }
  HDouble& operator/=(const HDouble& OtherValue)
  {
    dValue /= OtherValue.dValue;
    return *this;
  }
  //////////////////////////////////////////////////////////////////////////


  inline bool IsNaN(double d) 
  {
    if (!(d >= DBL_MIN && d <= DBL_MAX))
    {
      return true;
    }
    else
      return false;
  }
};

one problem is like a function that already exist calls cos() function for example and it expects a double. is there a way for my class object to decay to an intrinsic double when needed? thanks.

p.s. my class must fit seamlessly with the existing code. cant change that. all i can do is search and replace double with HDouble.

  • 1
    override the cast: http://www.cplusplus.com/forum/general/25434/ – TJD Sep 21 '12 at 21:16
  • 4
    A class like that has zero chance of fitting seamlessly in place of double, because it breaks a fundamental rule of mathematical equality: your `==` is no longer transitive. When you see `a==b` and `b==c`, you cannot imply that `a==c`. Unfortunately, this is where it all breaks down: a class without a reliable `==` operator is useless. This mistake is both common and old: I remember reading Dijkstra's account of making the same mistake in the context of writing an Algol compiler. – Sergey Kalinichenko Sep 21 '12 at 21:17
  • It's worth mentioning (for the future, maybe) that since C++11, you can make explicit conversion operators so that no implicit conversions happen. – chris Sep 21 '12 at 21:17
  • 3
    This is a **really bad idea**. – Pete Becker Sep 21 '12 at 21:37
  • Seconded. This is an awful idea. – Ed S. Sep 21 '12 at 21:55
  • `if (!(d >= DBL_MIN && d <= DBL_MAX))` I like how that declares infinities, subnormals, 0, and negative numbers as `NaN`. – Daniel Fischer Sep 21 '12 at 22:58

3 Answers3

0

Yes, add a conversion operator to your class: operator double() { return dValue; } to your class. That way your HDouble will be converted to a double when you pass it to cos.

Also, you have implemented all your operators as member functions. I would suggest reading about operator overloading.

Community
  • 1
  • 1
Jesse Good
  • 50,901
  • 14
  • 124
  • 166
0

You can add a method to return the double:

double value()
{
    return dValue;
}
John
  • 15,990
  • 10
  • 70
  • 110
0

You need to add a copy constructor and a conversion operator to your class, and you should also move the class's data member to private:

class HDouble 
{ 
private: 
  double dValue; 

public: 
  static const double dEpsilon; 

  HDouble() 
  { 
    dValue = 0.0; 
  } 

  HDouble(double OtherValue) 
  { 
    if (IsNaN(OtherValue)) 
    { 
      assert(0); 
    } 
    dValue = OtherValue; 
  } 

  HDouble(const HDouble &src) 
  { 
    dValue = src.dValue; 
  } 

  ...

  operator double() const
  {
    return dValue;
  }

  ...
}; 
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770