Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 424
  • Last Modified:

How can a C++ class account for both double and floating points?

How can I account for both doubles and floating points using the following code:

public:
    Literal(double value)
    {
        this->value = value;
    }
    double evaluate()
    {
        return value;
    }
private:
    int value;
};
0
NSing9
Asked:
NSing9
  • 12
  • 10
  • 2
  • +3
2 Solutions
 
logic_chopperCommented:
Well I would use a class template, this way you can also avoid the cast to "int" which may create subtle problems with your program with loss of precision.

template <class T>
...
public:
    Literal(Tvalue)
    {
        this->value = value;
    }
    T evaluate()
    {
        return value;
    }
private:
    T value;
};
0
 
TommySzalapskiCommented:
Just make
int value
be
double value

You can set a double equal to a float, a double, or an int and it will keep the right value. It will always be correct up to, like, 12 decimal places.
0
 
phoffricCommented:
>> How can I account for both doubles and floating points
The above comments both make sense.
FYI - if you call  Literal(double value) with a float, then the compiler will promote tha value to a double with no loss in precision in this pass-by-value. (But, as mentioned, the int <- double statement can cause pecision loss.)
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
Subrat (C++ windows/Linux)Software EngineerCommented:

FYI:
By default all the real no.s are double.
Ex: 7.0 ----------------------------- > it's a double value not a float

To make it float you need to use suffix f
Ex: 7.0f  -------------------------------- > It's a float value
0
 
trinitrotolueneCommented:
it also is a question of how you design your class. If the objects are going to be encapsulations of integers only and you don't foresee any changes which is highly unlikely then you should probably have your constructor interfaces reflecting this. So have a constructor which takes only an integer. Do some pre-processing to round off the float or double input you receive before passing it to the constructor.

float ft = somenum;
int it = ceil/floor(ft); //use ceil or floor depending on your needs.

call your constructor which takes an integer as argument.

Literal lt = Literal(it);

This approach also implies that you can overload your constructor to take a float argument in order to create an object which encapsulates float values.

Else the best approach to go for is to templatize the class as has been already pointed out by experts in previous posts.
0
 
NSing9Author Commented:
I have tried the Templae approach, but when I compile my pgoram I get an error message in another class that is associated with the Literal class referenced above.  The error in the other class is associated with this line of code:

Expression* literal = new Literal(value);

error C2955: 'Literal' : use of class template requires template argument list
error C2514: 'Literal' : class has no constructors
      
0
 
phoffricCommented:
If you post all your code, someone will be able to help you better.
0
 
logic_chopperCommented:
You will need to specify a template parameter, so for example, the code that you have shown could be changed to:
Expression<double>* literal = new Literal<double>(value);
0
 
NSing9Author Commented:
I have attached the two classes that I believe are affected by this change.  I don't want to attach everything because there are quite a few more.   The error message that I receive is associated with Literal in the operand.cpp file.
operand.cpp
literal.h
0
 
phoffricCommented:
>> template <class T>
>> class Literal: public Operand
Given that Literal is a templated class, you need to let the compiler know what type to use. For example, with vector, you might say:


vector<int> myIntVector;

Open in new window

0
 
phoffricCommented:
If Literal were a templated function rather than a class, then the compiler would try to figure out what code should be generated.
0
 
NSing9Author Commented:
Simply changing the line of code to:

Expression<double>* literal = new Literal<double>(value);

doesn't compile.  I get a few errors:

error C2143: syntax error : missing ';' before '<'
error C2143: syntax error : missing ';' before '<'      
error C2065: 'literal' : undeclared identifier      
0
 
phoffricCommented:
If you post all your code, someone will be able to help you better.
0
 
NSing9Author Commented:
There are too many files to post.  I have already attached the two files where the changes are being made and that are generating the errors.  I will post the code for the file that is generating the error here:

#include <cctype>
#include <iostream>
#include <list>
#include <string>

using namespace std;

#include "expression.h"
#include "subexpression.h"
#include "operand.h"
#include "variable.h"
#include "literal.h"
#include "parse.h"

Expression* Operand::parse()
{
    char paren;
    double value;

    cin >> ws;
    if (isdigit(cin.peek()))
    {
        cin >> value;
        Expression<double>* literal = new Literal<double>(value);
        return literal;
    }
    if (cin.peek() == '(')
    {
        cin >> paren;
        return SubExpression::parse();
    }
    else
        return new Variable(parseName());
    return 0;
}
0
 
phoffricCommented:
You never showed your definition of Expression.
0
 
NSing9Author Commented:
My apologies:

#include <iostream>
using namespace std;

#include "SyntaxException.h" // SyntaxException class

#include "expression.h"
#include "subexpression.h"
#include "operand.h"
#include "plus.h"
#include "minus.h"
#include "times.h"
#include "divide.h"

SubExpression::SubExpression(Expression* left, Expression* right)
{
    this->left = left;
    this->right = right;
}

Expression* SubExpression::parse()
{
    Expression* left;
    Expression* right;
    char operation, paren;
   
    left = Operand::parse();
    cin >> operation;
    right = Operand::parse();
    cin >> paren;
      switch (operation)
    {
        case '+':
            return new Plus(left, right);
        case '-':
            return new Minus(left, right);
        case '*':
            return new Times(left, right);
        case '/':
            return new Divide(left, right);
            default:
                  throw SyntaxException();
    }
    return 0;
}
       
0
 
phoffricCommented:
Could you show (in the code box) the file that defines the class Expression, SubExpression, and Variable. That may help. If there are other class definitions that are potentially involved in the errors, that may help.
0
 
NSing9Author Commented:
This is the same file that I posted in the previous comment.  So I hope I am posting it here correctly.
#include <iostream>
using namespace std;

#include "SyntaxException.h" // SyntaxException class

#include "expression.h"
#include "subexpression.h"
#include "operand.h"
#include "plus.h"
#include "minus.h"
#include "times.h"
#include "divide.h"

SubExpression::SubExpression(Expression* left, Expression* right)
{
    this->left = left;
    this->right = right;
}

Expression* SubExpression::parse()
{
    Expression* left;
    Expression* right;
    char operation, paren;
    
    left = Operand::parse();
    cin >> operation;
    right = Operand::parse();
    cin >> paren;
      switch (operation)
    {
        case '+':
            return new Plus(left, right);
        case '-':
            return new Minus(left, right);
        case '*':
            return new Times(left, right);
        case '/':
            return new Divide(left, right);
            default:
                  throw SyntaxException(); 
    }
    return 0;
}

Open in new window

0
 
NSing9Author Commented:
Here is the variable class:
#include <strstream>
#include <vector>
using namespace std;

#include "UninitializedException.h" //
#include "expression.h"
#include "operand.h"
#include "variable.h"
#include "symboltable.h"

extern SymbolTable symbolTable;

double Variable::evaluate()
{
	if (symbolTable.lookUp(name) == -1)		//
		throw UninitializedException(name);		// terminate function

	return symbolTable.lookUp(name);
}

Open in new window

0
 
phoffricCommented:
Yes, that makes posting code much easier, and now we can refer to line numbers. But the definitions of the classes Expression, SubExpression, and Variable are still not shown. They begin with, for example:

class Expression {
}

or if templated,
template <class T>
...
0
 
NSing9Author Commented:
I am new to C++ so forgive me for not understanding all of the terminology.  Since you are asking for definitions, I assume you are refering to the .h files.
class Expression
{
public: 
    virtual double evaluate() = 0;
};

class SubExpression: public Expression
{
public:
    SubExpression(Expression* left, Expression* right);
    static Expression* parse();
protected: 
    Expression* left;
    Expression* right;
};


class Variable: public Operand
{
public:
    Variable(string name)
    {
        this->name = name;
    }
    double evaluate();
private:
    string name;
};

Open in new window

0
 
phoffricCommented:
The .h files are helpful. How about Operand, and any other .h useful for us to recreate your problem.
0
 
NSing9Author Commented:
I have inlcuded symboltable.h and operand.h.  Going back to my original post and another response that was received, would changing:

int value;
to
double value

in the Literal definition not suffice?


class Operand: public Expression
{
public:
    static Expression* parse();
};

class SymbolTable
{
public:
    SymbolTable() {}
    void insert(string variable, double value);
    double lookUp(string variable) const;
private:
    struct Symbol
    {
        Symbol(string variable, double value)
        {
            this->variable = variable;
            this->value = value;
        }
        string variable;
        double value;
    };

    vector<Symbol> elements;
};

Open in new window

0
 
phoffricCommented:
Try this:
Expression* literal = new Literal<double>(value);

Open in new window

0
 
phoffricCommented:
The previous similar posts made assumptions about the Expression class. But without your class definitions (which you put in your .h files), it was only reasonable guessing.
0
 
NSing9Author Commented:
Thank you!  This finally worked!
0
 
phoffricCommented:
You're welcome.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 12
  • 10
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now