NSing9
asked on
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;
};
public:
Literal(double value)
{
this->value = value;
}
double evaluate()
{
return value;
}
private:
int value;
};
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> 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.)
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.)
FYI:
By default all the real no.s are double.
Ex: 7.0 --------------------------
To make it float you need to use suffix f
Ex: 7.0f --------------------------
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.
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.
ASKER
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
Expression* literal = new Literal(value);
error C2955: 'Literal' : use of class template requires template argument list
error C2514: 'Literal' : class has no constructors
If you post all your code, someone will be able to help you better.
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);
Expression<double>* literal = new Literal<double>(value);
ASKER
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
operand.cpp
literal.h
>> 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:
>> 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;
If Literal were a templated function rather than a class, then the compiler would try to figure out what code should be generated.
ASKER
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
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
If you post all your code, someone will be able to help you better.
ASKER
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;
}
#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;
}
You never showed your definition of Expression.
ASKER
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::SubExpressi on(Express ion* 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;
}
#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::SubExpressi
{
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;
}
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.
ASKER
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;
}
ASKER
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);
}
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>
...
class Expression {
}
or if templated,
template <class T>
...
ASKER
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;
};
The .h files are helpful. How about Operand, and any other .h useful for us to recreate your problem.
ASKER
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?
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;
};
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
ASKER
Thank you! This finally worked!
You're welcome.
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.