Click here to Skip to main content
15,867,568 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
Hello

As part of a personal project, I need to make a console based Scientific calculator.

It needs to be able to add, subtract, multiply and divide a large amount of numbers per command (eg: 2+2+2+2+2+2*9/7*sin 45- 88.277) and be able to manipulate numbers correctly using BIDMAS.

It needs to be able to compute trigonometry functions, logarithms, mod of an integer, calculate factorials and calculate exponents and roots to the nth degree.

How can I go about doing this and how many lines of code will it take?

I do not want it to have a GUI at the moment.

Any source code will be released and the entire program will be free.


I have looked around for ages and all I can find are calculators which can only add two numbers

Thanks very much in advance
Posted
Updated 6-Apr-23 13:29pm
Comments
Sergey Alexandrovich Kryukov 4-May-12 17:38pm    
Reason for my vote of 2
Pointless.
--SA

This is mainly a parsing task, not really suited for a C++ beginner.
An expert in parsing would solve this within a few hours - a complete novice might take months to get it somehow done.
I would choose a different topic, depending on your personal interests or hobby.
Think also of where C++ is useful today and choose a respective topic.

If you insist on a parser task in C++, you might take flex/bison and learn
- tokeinzing (define tokens)
- parsing (define productions)
- symbol table (type system, variable/operator/function lookup, storing and retrieving data, supported operations, executing operations)
- actions (define actions for parsed productions and how to pass values around, e.g. by a stack)

You might need to buy a book on compiler construction.

Good luck.

Andi
 
Share this answer
 
It is not going to be easy, and going to need more lines of code than you think.

You will need to parse the input string to search for the symbols and the numbers, differenciate the trigonometry functions, check spelling (possibly giving errors or autocorrection), add the () where needed (what means: find a "*" or a "/" or a number followed by letters "2sin 45", and then search to the back and to the front to set the priority of the operations) and more... and that, only to read the input.

Then call the respective operations following the priority order and dealing with the exceptions (like diving by 0, imaginary roots, and so on).

In conclusion... too wide thema just to explain at once.


Start coding and come back when you get more concrete problems, you will get better answers and more usefull help if you delimitate the questions to a particular issue.

Good luck and have fun coding :)
 
Share this answer
 
Comments
Cameron Handoe 4-May-12 18:25pm    
Thank you very much for the reply! I'll get to work very soon.

Just a question, how do I store so many variables? All the calculators I have seen so far assign values to global variables and thus are very limited. How can I get around this?
Sergey Alexandrovich Kryukov 4-May-12 19:29pm    
I think starting from parser is a waste of time, unless someone wants to learn parsing.

One approach is interpretive languages like JavaScript (with Eval) -- you can parse, interpret and run code supplied from user's data (please see my comment to my solution).
Another approach is CodeDom.

--SA
You might also uses boost if you want to do it in C++ (or in mixed mode with C++/CLI).

http://www.boost.org/doc/libs/1_49_0/libs/spirit/doc/html/index.html[^]

For the number of lines of code, it would depends a lot on how you do it...
 
Share this answer
 
Comments
Cameron Handoe 5-May-12 10:12am    
Please pardon my ignorance however I am a beginner.

What do these Boost liveries enable me to do?
Philippe Mori 5-May-12 18:21pm    
Well the provided link point to the documentation for a library for parsing. I have never used it but it should help a lot doing a parser but you will also have a lot of thing to learn. Start with the introduction and then the tutorial.

What I do know is that boost come with a lot of library done by expert and some of the libraries become part of the standard library. In my case, since I mainly write managed code (C# and C++/CLI), then boost is less applicable.
Abdelrahman Elzedy 4-Jan-13 17:36pm    
I think this code will help you
Best wishes
There is nothing specific about it: to have the code, you need to design, develop and debug it. Instead of looking around for ages. What to ask about? If you are not a software developer, this forum is not for you, but if you are — just get to work.
Nobody can tell you how many lines of code will you need. How counts those lines? Anyway, this is your code. Who knows your skills and style?

I also would be curious: why would you need a calculator at all? There are many ways to calculate things.

If you have any specific concerns, please ask a question, we will gladly try to help you.

—SA
 
Share this answer
 
Comments
Cameron Handoe 4-May-12 18:24pm    
It's just a bit of fun and a coding exercise. I am fairly new and I want to evaluate my abilities so far.

Thanks for the reply, I appreciate it.

I just wanted to know what would be the best method to be able to to this
Sergey Alexandrovich Kryukov 4-May-12 19:27pm    
Well, for fun or not, it does not change technology. If you do it and face some problems, I would try to help.
Here is why I'm asking "why calculator": for example: JavaScript is already a calculator, because you can use Eval, that is, you can use JavaScript to interpret code and present result. Please see mine:
http://sakryukov.org/freeware/calculator/.
It's only few line of JavaScript code.
More advanced approach (but why?) is using CodeDom to compile end execute code during run-time. It also frees you from parsing exception, because you can use C# or VB.NET for expression compiler. The compilers come for free with .NET.
--SA
Cameron Handoe 5-May-12 8:31am    
Wow! That code is impressive!

The reason why I wanted to code it in C/C++ is simply because I am learning C/C++ and I wanted a challenge.

Obviously you are an expert. I just need to know the best way to store variables so that my calculator isn't limited
Sergey Alexandrovich Kryukov 8-May-12 13:30pm    
If you like my idea, will you accept the answer formally (green button)? -- thanks.
I don't really understand your issue with storing of variables. If you need to make a calculator with expression (the only one which makes some sense), you would need to parse expression into a tree and store everything in this tree. Try to search CodeProject:

http://www.codeproject.com/search.aspx?doctypeid=1&q=%22C%2b%2b%22+expression+%28parser+OR+evaluator%29

--SA
SajeeshCheviry 5-Jan-13 2:24am    
You are absolutely right
C#
//scientific calculator in c++
//written by Abd - elrahman Elmasry
//e-mail: abdoasemelzedy@hotmail.com
//there is no copy right for this code


#include<iostream>//main library
#include<math.h>// for mathimatics function
#include<stdexcpt.h>//for exeption conditions

using namespace std;

class calc
{
private:
    int len,//for the length of array
        intPartTemp,//for using its value
        intLen,//for the len of integer part
        floatLen,//for the len of float part
        ten,//for pow function
        str;//for deter mine starting point

    double value,//for the value of mid
        floatPartTemp,//for getting floating part of numbers for converting
        x; // for the value of variable x

    char ch[1000] ;//charchters for saving formulas
    char carriage[100];//for putting num in it as a caracter
    char copy [1000];//for saving user formula

//getting information form user
    void setInfo()
{
    cin.getline(copy,1000);//getting formulas from user
    copyArray(copy, ch);//copy array to save its value
    replace(x,'x');//replacing variable x with its value
}

void copyArray (char main [], char copy [] )
{
    //getting main array lenght
    int len = strlen(main);
    int temp;

    //it counts to null because of null
    for(temp=0;temp<=len;temp++)
    {
        copy[temp] = main[temp];
    }
}


//editing formulas to be adaptable to computing rules
void edit()
{//star edit
    int temp;

    len = strlen(ch);

    for(temp=0;temp<len;temp++)
    {//loop for cover all characters

        //the condition there is two variables after them thelf without *
         if(!triangleMove(temp) && isalpha(ch[temp]) && isalpha(ch[temp+1]) )
            //not triangle to make sure they aren't triangle functions
            insert(temp,len,'*');

        //the condition when there is a number and after it a variable without *
        else if(temp!=0 && isalpha(ch[temp]) && isdigit(ch[temp-1]))
            insert(temp,len,'*');

        //the condition there is two parentheses after them thelf without *
        else if(temp!=0 && ch[temp] == '(' && ch[temp-1] ==')' )
            insert(temp,len,'*');

        //the condition when there is a number before (
        else if(temp!=0 && ch[temp] == '(' && isdigit(ch[temp-1]) )
        insert(temp,len,'*');

        else if( ( ch[temp]=='.' && temp == 0) || ( temp>0 && ch[temp] == '.' && !isdigit( (ch[temp-1]) ) ) )
            insert(temp,len,'0');

        //the condition when there is ++
        else if( ch[temp] == '+' && ch[temp+1] =='+' )
            smaller(temp,len,'+');

        //the condition when there is ++
        else if( ch[temp] == '+' && ch[temp+1] =='-' )
            smaller(temp,len,'-');

        //the condition when there is ++
        else if( ch[temp] == '-' && ch[temp+1] =='-' )
            smaller(temp,len,'+');

        //the condition when there is ++
        else if( ch[temp] == '-' && ch[temp+1] =='+' )
            smaller(temp,len,'-');

    }//end loop of coverting

    //the condition when first digit is +
    if(ch[0]=='+')
        decrease(0,1);

}//end edit

//for examing formulas from being out of math rules
bool exam ()
{
    int leftBracket=0,//for count left brackts
        rightBracket=0,//for count right brackt
        len = strlen(ch), // for array lenght
        temp;//temprature variable

    for(temp = 0; temp<len; temp++)
    {
        //continue defaule condition of being number
        if( isdigit(ch[temp]) )
            continue;

        //count left brackets
        else if(ch[temp] == '(')
            leftBracket ++;

        //count right brackets
        else if(ch[temp] == ')')
            rightBracket ++;

        //the condition of being two mathimatics symbols after themself
        else if( !isalpha(ch[temp]) && !isalpha(ch[temp+1]) && !isdigit(ch[temp+1]) )
            return false;

    }//end covering loop

    //false formulas with right brackets not equal leftbrackets
    if(rightBracket != rightBracket)
        return false;

    //condition with the last idgits isn't number or ')'
    if( !isdigit (ch[len-1] ) && ch[len-1] != ')'  )
        return false;

    //defaule condition
    return true;
}


//for moving temp
bool triangleMove(int &temp)
{

    //sin condition
    if(ch[temp] == 's' && ch[temp+1] == 'i' && ch[temp+2] == 'n' && ch[temp+3] == '(' && isdigit(ch[temp+4]) )
    {
        temp+=4;//for going to next element
        return true;
    }

    //cos condition
    else if(ch[temp] == 'c' && ch[temp+1] == 'o' && ch[temp+2] == 's' && ch[temp+3] == '(' && isdigit(ch[temp+4]) )
    {
        temp+=4;//for going to next element
        return true;
    }

    //tan condition
    else if(ch[temp] == 't' && ch[temp+1] == 'a' && ch[temp+2] == 'n' && ch[temp+3] == '(' && isdigit(ch[temp+4]) )
    {
        temp+=4;//for going to next element
        return true;
    }

    //defaul condition
    return false;
}

//examing triangle functions
bool triangle (int temp)
{

    //sin condition
    if(ch[temp] == 's' && ch[temp+1] == 'i' && ch[temp+2] == 'n' && ch[temp+3] == '(' && isdigit(ch[temp+4]) )
    {
        return true;
    }

    //cos condition
    else if(ch[temp] == 'c' && ch[temp+1] == 'o' && ch[temp+2] == 's' && ch[temp+3] == '(' && isdigit(ch[temp+4]) )
    {
        return true;
    }

    //tan condition
    else if(ch[temp] == 't' && ch[temp+1] == 'a' && ch[temp+2] == 'n' && ch[temp+3] == '(' && isdigit(ch[temp+4]) )
    {
        return true;
    }

    //defaul condition
    return false;
}

void increase (int order,  int &len, int count)
{//for increaseing array's element
    int temp, temp2;

    //punt any digit

    for(temp2=0; temp2<count; temp2++)
{
    len++;//increase len by one for the new character

    for(temp=len;temp>order;temp--)
    {//increase array with one starting with last element
        ch[temp]=ch[temp-1];
    }
}
}//end increase function

void decrease (int order, int count)
{//for increaseing array's element
    int temp, temp2;
    int len = strlen(ch);
    for(temp2=0;temp2<count;temp2++)
{

    for(temp=order;temp<len;temp++)
    {//increase array with one starting with last element
        ch[temp]=ch[temp+1];
    }
    len--;//increase len by one for the new character
}
}//end increase function

void insert(int order,  int &len, char ob)
{//for puting an element in some order

    //increase characters
    increase (order, len,1);
    //put requred element in its position
    ch[order] = ob;

}//end insert function

void smaller(int order,  int &len, char ob)
{//for shorting two elements with one as ++ to be +

    //decrease
    decrease(order, 1);
    //put requred element in its position
    ch[order] = ob;

}//end smaller function

int getNumLen(double num)
{//for the lenght of a num to put it in a character

    int intPart,//for the  integer part
        temp, //temprature variable
        numLen;//for the lenght of the num

    bool plus = false;

    double floatPart;//for the float part

    if(num<0)
    {
        plus = true;
        num*=-1;
    }


    //determine integer part
    intPart = intPartTemp = static_cast<int>(num);
    floatPart = floatPartTemp = num - intPart;

    //getting integer part lenght
    for(intLen=0;intPart>0;intPart/=10)
    {
        intLen++;
    }

    if(intLen == 0)
        intLen = 1;//for making a digit for 0

    //getting integer part lenght
    //initializing floatLen with 1 for '.'
    floatPart>0?floatLen=1:floatLen=0;
    for(temp= 1; floatPart!=0 && floatLen<10 ; floatLen++)
    {
        floatPart*=10;//put one digit in the integer part
        temp = static_cast<int>(floatPart) ;
        floatPart-=temp;//remove the digit
    }

    if(plus){
        intLen++;//increase digit for -
        intPart *=-1;
    }
    numLen = intLen + floatLen;



    return numLen;
}//end getLength function

void convert(char carriage[], double num, int intLen, int intPart, int floatLen, double floatPart, int numLen, bool sign )
{
    int temp1, temp;
    int start = 0;

        //making the first position for 0 in the condition
        //of numbers less than 1

        if(numLen>0)
        {
            carriage[numLen]=0;
        }
        else
        {
            numLen=1;
            carriage[numLen]=0;
        }

        //negative conditions
    if(!sign){
        start ++;
        carriage[0] = '-';
    }


    //integer part
    for(temp=intLen-1;temp>=start;temp--)
    {
        temp1= intPart % 10 ;//getting the first digit
        carriage[temp]= temp1+48;//put the first digit

        intPart/=10; //remove the first digit
    }

    //floating part

    //move null to next position
    if(floatPart!=0){

        //intLen as null in this time is in intLen position
        carriage[intLen]='.';
        carriage[intLen + floatLen ]=0;

        //starting with intLen because of int part and .
    for(temp=intLen+1;temp<floatLen+intLen; temp++)
    {
        floatPart*=10;//put one digit in the integer part
        temp1 = floatPart;//get the digit and put it in integer variable
        carriage[temp]=temp1+48;//get the digit in the integer part
        floatPart-=temp1;//remove the digit
    }

    }//end if

}//end convert function

void replace ( double num, char var)
{//for replacing a variable with a numberical value
    int len = strlen(ch);
    int temp;

    for(temp=0;temp<len;temp++)
    {
        if(ch[temp]==var)
        {
            decrease(temp,1);//remove variable
            insertNum(temp,  num);//replace variable with the number
        }//end if
    }//end for
}//end replace


double getFloatNum (int &position, int count)
{

    double num; //for the return

    int temp;//for looping
    int arrange;

    ten = 10;//decleration ten
    num = 0;//initialize num with 0
    arrange=1;

    //intger part
    for(temp=0; isdigit(ch[position]) && temp<count; temp++)
    {

        num = num + (ch[position++]-48)/pow(ten,static_cast<double>(arrange++));
    }

    position--;
    //because it will be increase with the loop
return num;
}//end getNum for floating


double getNum (int &position)
{

    double num, //for the return
            floatPart; // for floating parts

    double sign = 1;//for the numbers'sign 1 is positive

    ten = 10;//decleration ten
    num = 0;//initialize num with 0

    //because we start get the num from its first numerical digit
    if(ch[position]=='-')
        position++;

    if( (position>0 && ch[position-1] == '-') || (position==0 &&ch[position] =='-') )
    {
        sign = false;
    }

    //intger part
    while(isdigit(ch[position]))
    {
        num = num *10 + ch[position]-48;
        position++;
    }
    position--;//return to last numerical digit

    //because it will be increase with the loop

    if(ch[position+1]=='.')
    {
        position+=2; //for going to the num position
        floatPart = getFloatNum(position, 5);

        num = num + floatPart ;
    }

    if(!sign)
        num*=-1;

    return num;
}

bool check(int temp, double &num1 , double &num2, char &symbol)
{

    int len1,//for the lenght of num1
        len2;//for the lenght of num2


    num1 = getNum(temp);
    len1 = getNumLen(num1);

    while(isdigit(ch[temp]))
    temp++;

    temp--;//to be at the last digit

    if(ch[temp+1]!=0 && !isdigit(ch[temp+1]) )
    {

    //getting process symbol
    symbol = ch[++temp];

    //for going to next num after process symbol
    num2 = getNum (++temp);
    len2 = getNumLen (num2);


    return true;
    }//end if condition

    else
        return false;
}

void trigon_op(int &temp)
{

    double num,//result value
            insNum;//insert num

    int numLen;//the lenght of the number
        len = strlen(ch);
    //sin condition
    if(ch[temp]=='s' && ch[temp+1] =='i' && ch[temp+2] =='n')
    {
        //going for number position
        //three for s, i, n and one for '('
        temp+=4;

        //inside num
        insNum = getNum(temp);

        numLen= getNumLen(insNum);

        //return for the main positioin
        temp-=3+numLen;

        //the five are for s, i, n, (, )
        decrease(temp,numLen+5);

        num=sin(insNum);

        insertNum(temp, num);
        temp+=getNumLen(num);
    }

    //cos condition
    else if(ch[temp]=='c' && ch[temp+1] =='o' && ch[temp+2] =='s')
    {
        //going for number position
        //three for c, o, s and one for '('
        temp+=4;

        //inside num
        insNum = getNum(temp);

        numLen= getNumLen(insNum);

        //return for the main positioin
        temp-=3+numLen;

        //the five are for c, o, s, (, )
        decrease(temp,numLen+5);

        num=cos(insNum);

        insertNum(temp, num);

    }

    //tan condition
    else if(ch[temp]=='t' && ch[temp+1] =='a' && ch[temp+2] =='n')
    {
        //going for number position
        //three for t, a, n and one for '('
        temp+=4;

        //inside num
        insNum = getNum(temp);

        numLen= getNumLen(insNum);

        //return for the main positioin
        temp-=3+numLen;

        //the five are for t, a, n, (, )
        decrease(temp,numLen+5);

        num=tan(insNum);

        insertNum(temp, num);
    }
}

//for getting str and end values
void getBorders(int &str, int &end)
{
    int len = strlen(ch) -1 ;
    int temp;
    str=0;//initial value
    end = len;//initial value

    for(temp=0;temp<len;temp++)
    {

    if(temp>0 && ch[temp]=='(' && !isalpha(ch[temp-1]) )
        str=temp+1;

    else if(str > 0 && ch[temp]== ')' && !isalpha(ch[str-1]) )
    {
        end = temp;
        break;
    }

}//emd for



}

void process (double num1, double num2, char symbol, int temp)
{//processing operations


    int len1 = getNumLen(num1),
         len2 = getNumLen(num2),//for num1 and num2 lenght
        len = strlen(ch);//for the size of array
        int count;//for the position of removing and insertion

    double num; // for the result

    if(symbol == '^')
        num = pow(num1,num2);

    else if(symbol == '*')
        num = num1*num2;

    else if(symbol == '/')
        num = num1/num2;

    else if(symbol == '+')
        num = num1+num2;

    else if(symbol == '-')
        num = num1+num2;// + because it will be taken as negative before

        //len1 for removing num1
        //len2 for removing num2
        //1 for removing symbol

    if(num2 >= 0 && num1 >=0) //in this condition the lenght of of num1 and num2 are real
        count = len1+len2;

    //in this condition the lenght of of num2 is real and num1 is with negative sign so we should remove it
    else if(num2 >= 0 && num1 <0)
        count = len1+len2;


    //in this condition the lenght of of num1 is real and num2 is with negative sign so we should remove it
    else if(num2 < 0 && num1 >=0)
        count = len1 + len2;

    //in this condition the lenght of of num1  and num2 are with negative signs so we should remove them
    else if(num2 < 0 && num1 <0)
    {
        count = len1 + len2 ;
        temp--;//to be at negativ sign
    }
    if(symbol != '-')
        count ++ ;

    //decrease ch form numbers are members of operation
    decrease(temp,count);


    insertNum(temp,num);
    //starting removing from the first digit of num1
        //as we set now on the last digit of num2

        //reedit the formula
        edit();
}

void semiMath(int str, int end, char ch[])
{
    int temp,
        zero = 0;//for getNum function

    char symbol;

    double num1, // for the first number for operating
            num2;//for the second number for operating

    len = end;

    //trigon function stage

    for(temp=str;temp<len;temp++)
    {
        if(triangle(temp))
        {
            trigon_op(temp);
            getBorders(str,end);
            temp = str -1;//return to first digit after increasing loop to process anothers
            len=end+1;
        }
    }
    //first stage
    len = end;
    for(temp=str;temp<len;temp++)
    {//starting covering the formula with loop

            if( (isdigit(ch[temp]) || ch[temp]=='-' ) && check(temp, num1, num2, symbol) )
            {
                if(symbol == '^')
                {
                    process(num1,num2,symbol,temp);
                    getBorders(str,end);
                    temp = str -1;//return to first digit after increasing loop to process anothers
                    len=end+1;}
            }
    }//end covering loop

    //second stage
    len = end;
    symbol = 0;//remove last symbol
    for(temp=str;temp<len;temp++)
    {//starting covering the formula with loop

            if( (isdigit(ch[temp]) || ch[temp]=='-' ) && check(temp, num1, num2, symbol) )
            {
                if(symbol == '*' || symbol == '/')
                {
                    process(num1,num2,symbol,temp);
                    getBorders(str,end);
                    temp = str -1;//return to first digit after increasing loop to process anothers
                    len=end;
                }
            }
    }//end covering loop

    //third stage
    len = end;
    symbol = 0;//remove last symbol
    for(temp=str;temp<len;temp++)
    {//starting covering the formula with loop

            if( (isdigit(ch[temp]) || ch[temp]=='-' ) && check(temp, num1, num2, symbol) )
            {
                if(symbol == '+' || symbol == '-')
                {
                    process(num1,num2,symbol,temp);
                    getBorders(str,end);
                    temp = str -1;//return to first digit after increasing loop to process anothers
                    len=end;
                }
            }
    }//end covering loop

}//end semi math

double math (char ch[], double x)
{
    int len = strlen(ch) ,//getting carachters' lenght
        temp, //temprature value
        zero = 0,
        end ;

    double  num;//for the final number

    edit();//edit formula to be adaptable to computing rules


    //loop for detemine str and end
if(exam())
{
for(temp = 0; temp <len; temp++)
{
    getBorders(str,end);

    semiMath(str, end,ch);

    len = strlen(ch);

    //if condition for removind ( ) after mathing
    if(str !=0)
    {
        getBorders(str,end);

        decrease(str-1,1);
        decrease(end-1 ,1);
        //end -1 because ')' will decrease one after removing (

    }//end if condition
}
    //getting final result
    num=getNum(zero);

    return num;
}

else
    throw invalid_argument(
    "Your formula is out of mathimatics rules");

}//end math function

void insertNum(int order, double num)
{//for insert a num to a character array
    int temp, numLen;
    int len;
     numLen = getNumLen(num);//determine the num's lenght
    bool sign;//for negativ conditions

     len = strlen(ch);

     if(num>=0)
         sign = true;
     else
         sign = false;

    convert(carriage,num,intLen,intPartTemp,floatLen,floatPartTemp, numLen, sign);

    //negative condition


    //starting loop with the last because it will be increase
    for(temp = numLen-1; temp>=0 ; temp--)
    {

        increase(order, len,1);
        ch[order] = carriage [temp];//tranport from carriage array
    }

}//end insert num
/////////////////////////////////////////////////////////////

public:

double getResult()
{
    setInfo();
    double num = math(ch,value);
    return num;
}

double getResult(char ch[], double value)
{
    double num = math(ch,value);
    return num;
}

};//end calc class

void main ()
{

    calc test;
    while(cout<<"= "<<test.getResult()<<endl<<endl<<endl);

}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900