views:

247

answers:

4

Hello my friends,

I'm having some issues with implementing a logarithm class with operator overloading in C++.

My first goal is how I would implement the changeBase method, I've been having a tough time wrapping my head around it.

I have tried to understand the math behind changing the base of a logarithm, but i haven't been able to. Can someone please explain it to me?

My second goal is to be able to perform an operation where the left operand is a double and the right operand is a logarithm object.

Here's a snippet of my log class:

// coefficient: double
// base: unsigned int
// result: double
class _log {

 double coefficient, result;
 unsigned int base;

public:

 _log() {
  base = 10;
  coefficient = 0.0;
  result = 0.0;
 }
 _log operator+ ( const double b ) const;
 _log operator* ( const double b ) const;
 _log operator- ( const double b ) const;
 _log operator/ ( const double b ) const;
 _log operator<< ( const _log &b );

 double getValue() const;

 bool changeBase( unsigned int base );
};

You guys are awesome, thank you for your time.

+5  A: 

My second goal is to be able to perform an operation where the left operand is a double and the right operand is a logarithm object.

To do this, you need to declare the operator as a non-member function at namespace scope (i.e., not in the definition of _log), e.g.,

_log operator+(const double a, const _log& b);

If you need access to the private members of _log, you can declare it as a friend inside the definition of _log:

friend _log operator+(const double a, const _log& b);

Note that names starting with an underscore (e.g., _log) are reserved to the implementation in the global namespace; if the underscore is followed by a capital letter or another underscore, it is reserved everywhere. It would be a good idea to choose a different class name.

James McNellis
In the non member operator case, it is nice to try to avoid saying friend. Since you already have a member addition operator, implementing the other direction as a non friend non member function in terms of that is trivial.
Stewart
+1  A: 

A few ideas:

  1. Don't name with a leading underscore. Such identifiers are radioactive in C and C++.
  2. Define operations between logarithms before operations with floats.
  3. Combine #2 with James' suggestion:

    friend logarithm operator+( const logarithm &l, const logarithm &r );
    
  4. Define a conversion constructor to generate a logarithm from a float:

    logarithm::logarithm( double f );
    

    Now C++ will convert the double to a logarithm in either 1.0 + my_log or my_log + 1.0.

  5. Implement natural logarithms in your class. Don't bother with base.
  6. Define base conversion in terms of a function:

    double alternate_base( double base ) const;
    

    Base conversion is simply dividing the logarithm by the natural log of the alternate base. It is probably most convenient to return the integer and fractional parts together in a single double.

Potatoswatter
+3  A: 

A few things

  1. Using an _ in the front of your class is a Very Bad Idea (tm). From the c++ standard:

17.4.3.2.1 Global names [lib.global.names] Certain sets of names and function signatures are always reserved to the implementation:

  • Each name that contains a double underscore (_ _) or begins with an underscore followed by an uppercase letter (2.11) is reserved to the implementation for any use.
  • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.165

165) Such names are also reserved in namespace ::std (17.4.3.1).

  1. I'm guessing that you used _log instead of log due to the clash with log() in cmath. It is a Very Bad Idea to keep your own classes in the standard namespace for this very reason. Maybe the next version of the standard will provide a _log or Logarithm class? Wrap your own class in namespace somename {} and reference it by using somename::Logarithm()

  2. As others have mentioned already You need to declare your operator overloading as friend. Instead of what you have

    log operator+ ( const double b ) const;

    change it to

    friend log operator+(const double d, const log& l);
    

    and define the function in the namespace scope.

  3. Here is the math for the change of base formula

    Change of base formula

  4. Coefficient in math means the part that is being multiplied by the log. So if you had A log_b(x) = y

    A is the coefficient, B is the base, and Y is the result (or some other names)

Good Person
A: 

Take care of Exceptions as well . log(0) log(-n)

S Sharma