//Funzioni:
#include <cmath>
#include <iostream>
using namespace std;
//Funzione "Pi di x", ovvero quanti numeri primi da 1 a x.
int Primidi (int a)
{
int b,d,c;
b=1;
d=0;
while (b<a)
{
b++;
c=2;
while (((b%c)!=0) && (c<=b))
c++;
if (c>=b)
{
d++;
}
}
return d;
}
//Calcola numero divisori
int numdiv (int a)
{
if (a<0)
a=-a;
int b,c=0;
b=1;
while (a>=b)
{
if (a%b ==0)
{
c++;
b++;
}
else b++;
}
return c;
}
//Fattoriale
double facto(int a)
{
if (a>0)
{
int i;
float b=1;
for (i=1;i<=a;i++)
{
b=b*i;
}
return b;
}
}
//Associa funzioni a char
float Fun (char a , float x)
{
/*Trigonometria*/
if (a=='s')
return sin(x);
if (a=='c')
return cos(x);
if (a=='t')
return tan(x);
if (a=='a')
return asin(x);
if (a=='b')
return acos(x);
if (a=='d')
return atan(x);
if (a=='h')
return sinh(x);
if (a=='i')
return cosh(x);
if (a=='j')
return tanh(x);
/*Logaritmi*/
if (a=='L')
return log10(x);
if (a=='N')
return log(x);
if (a=='D')
return (log(x))/(log(2.0));
/*Varie*/
if (a=='A')
return fabs(x);
if (a=='I')
return (int(x));
if (a=='P')
return Primidi(int(x));
if (a=='!')
return facto(int(x));
if (a=='V')
return numdiv(int(x));
/*Algebra*/
if (a=='R')
return sqrt(x);
if (a=='C')
return pow(float(x),float((1/3.0)));
if (a=='Q')
return pow(float(x),float((1/5.0)));
}
//Funione a tre parametri char che come risultato ridà il carattere-funzione da mettere nell'rpn
char charfun (char a, char b, char c)
{
int bo=0;
/*Trigonometria*/
if ((a=='s')&&(b=='i')&&(c=='n')){bo++;
return 's';}
if ((a=='c')&&(b=='o')&&(c=='s')){bo++;
return 'c';}
if ((a=='t')&&(b=='a')&&(c=='n')){bo++;
return 't';}
if ((a=='a')&&(b=='s')&&(c=='i')){bo++;
return 'a';}
if ((a=='a')&&(b=='c')&&(c=='s')){bo++;
return 'b';}
if ((a=='a')&&(b=='t')&&(c=='g')){bo++;
return 'd';}
if ((a=='s')&&(b=='n')&&(c=='h')){bo++;
return 'h';}
if ((a=='c')&&(b=='s')&&(c=='h')){bo++;
return 'i';}
if ((a=='t')&&(b=='a')&&(c=='h')){bo++;
return 'j';}
/*Logaritmi*/
if ((a=='l')&&(b=='o')&&(c=='g')){bo++;
return 'L';}
if ((a=='l')&&(b=='o')&&(c=='n')){bo++;
return 'N';}
if ((a=='l')&&(b=='o')&&(c=='d')){bo++;
return 'D';}
/*Varie*/
if ((a=='a')&&(b=='s')&&(c=='s')){bo++;
return 'A';}
if ((a=='i')&&(b=='n')&&(c=='t')){bo++;
return 'I';}
if ((a=='q')&&(b=='r')&&(c=='m')){bo++;
return 'P';}
if ((a=='f')&&(b=='a')&&(c=='c')){bo++;
return '!';}
if ((a=='d')&&(b=='i')&&(c=='v')){bo++;
return 'V';}
/*Algebra*/
if ((a=='r')&&(b=='a')&&(c=='d')){bo++;
return 'R';}
if ((a=='r')&&(b=='a')&&(c=='c')){bo++;
return 'C';}
if ((a=='r')&&(b=='a')&&(c=='q')){bo++;
return 'Q';}
if (bo==0)
{
return NULL;
}
}
//Converte le ascisse in coordinate x per la finestra
int conx(double s,float max)
{
int con;
con=int(500+(s*500/max));
return con;
}
//Converte le ordinate in coordinate y per la finestra
int cony(double s,float max)
{
int con;
con=int(500-(s*500/max));
return con;
}
//Controlla se il carattere nello stack è una funzione
int chkfun (char a)
{
if ((a=='s')||(a=='c')||(a=='t')||(a=='a')||(a=='b')||(a=='d')||(a=='h')||(a=='i')||(a=='j')||
(a=='L')||(a=='N')||(a=='D')||
(a=='A')||(a=='I')||(a=='P')||(a=='!')||(a=='V')||
(a=='R')||(a=='C')||(a=='Q'))
{
return 1;
}
else
return 2;
}
//Controlla se (nella Function Window) nella conversione RPN, un carattere è una costante (o una variabile) o un'operatore
int chkchar(char a)
{
if ((('0'<=a)&&(a<='9'))||(a=='x')||(a=='X')||(a=='p')||(a=='e')||(a=='y')) //Il carattere è una cifra, una costante o la variabile x.
{
return 1;
}
if ((a=='+')||(a=='-')||(a=='*')||(a=='/')||(a=='^')||(a=='%')) //Il carattere è un operatore
{
return 2;
}
else
return 3;
}
//Controlla la precedenza tra 2 operatori
bool precedence(char op1, char op2)
{
int first=0;
if ((op1=='+')||(op1=='-'))
{
first=1;
}
if ((op1=='*')||(op1=='/')||(op1=='%'))
{
first=2;
}
if ((op1=='^')||(chkfun(op1)==1))
{
first=3;
}
/*******************/
int second=0;
if ((op2=='+')||(op2=='-'))
{
second=1;
}
if ((op2=='*')||(op2=='/')||(op2=='%'))
{
second=2;
}
if ((op2=='^')||(chkfun(op2)==1))
{
second=3;
}
if ((first == second)||( first < second))
return false;
else
return true;
}
//Conta le cifre di un numero intero
float numcif (int a)
{
double aa=a;
if (a<0)
{
aa=-a;
}
double b;
float c;
b=log10(aa);
c=ceil(b);
if (c==b)
{
c++;
}
if (a==0)
{
c=1;
}
return c;
}
//Distanza tra due punti:
float dist(POINT a,POINT b)
{
float result;
result=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
result=sqrt(result);
return result;
}
//Solve RPN
float SolveRPN(string rpn,float x,float y)
{
stack <float> numbers;
string longNumber = "";
float result=0,prev=0,postv=0;
int chkop=0;
for (unsigned int h = 0; h < rpn.size(); h++)
{
/*Il carattere letto e' un numero. Questo numero viene memorizzato
* nella stringa di appoggio.
* Se il prossimo carattere e' un numero,vuol dire che nella
* stringa c'e un numero lungo perche' nella funzione di conversione
* dopo ogni numero inserito nella stringa di output veniva messo anche
* il simbolo di spazio. La prossima cifra del numero sara' aggiunta
* alla fine della stringa di appoggio all'aumentare dell'indice.
* Se il prossimo carattere non e' un numero, la stringa d'appoggio
* viene convertita in un numero vero e memorizzata nello stack. */
if(chkchar(rpn[h])==1)
{
if (isdigit(rpn[h]))
{
longNumber += rpn[h];
}
if ((rpn[h]=='x')||(rpn[h]=='X')) //sostitusco alla x nell'espressione il valore effettivo della x
{
numbers.push(x);
}
if ((rpn[h]=='y')) //sostitusco alla x nell'espressione il valore effettivo della x
{
numbers.push(y);
}
if (rpn[h]=='e') //sostituisco alla e nell'espressione il valore della costante
{
numbers.push(2.71828);
}
if (rpn[h]=='p') //sostituisco alla p nell'espressione il valore della costante
{
numbers.push(3.14159);
}
//Se il carattere successivo non è una cifra e è diverso dalla virgola:
if((!isdigit(rpn[h + 1]))&& (rpn[h+1]!='.')&&(rpn[h]!='x')&&(rpn[h]!='X')&&(rpn[h]!='e')&&(rpn[h]!='p')&&(rpn[h]!='y'))
{
numbers.push(atof(longNumber.c_str()));
longNumber = "";
}
if (rpn[h+1]=='.') //Se il carattere successivo è la virgola:
{
numbers.push(atof(longNumber.c_str())); //legge la parte precedente a questa (la parte intera )
longNumber = "";
prev = numbers.top();
numbers.pop();
int count=2;
while (isdigit(rpn[count+h])) //Legge la parte successiva e la memorizza come numero
{
longNumber += rpn[h+count];
count++;
}
h=h+count;
postv=(atof(longNumber.c_str()));
longNumber="";
/*somma la parte precedente a quella successiva
fratto 10^il numero di cifre che ha es:
2.985 prev=2 postv=985
985 ha tre cifre quindi 985/10^3=0.985
li sommo e ottengo 2.985*/
numbers.push(prev+(postv/pow(10,numcif(postv))));
postv=0;prev=0;
}
}
if (chkchar(rpn[h])==2) //Il carattere è un operatore:
{
chkop++; //Controlla se vi è un operatore
result = numbers.top();
numbers.pop();
if (numbers.empty()) //se c'è un operatore all'inizio, è come se ci fosse lo 0 (es.-6=0-6)
{ //pertanto aggiungo lo 0
numbers.push(0.0);
}
/*****OPERATORS****************************************/
switch(rpn[h])
{
case '+':
result = numbers.top() + result ;
break;
case '-':
result = numbers.top() - result ;
break;
case '*':
result = numbers.top() * result ;
break;
case '/':
result = numbers.top() / result ;
break;
case '^':
result = pow(numbers.top() , result) ;
break;
case '%'://Operatore modulo
if (((int) numbers.top()!=0)&&((int) result!=0))
result =int(numbers.top()) % int(result) ;
break;
}
numbers.pop();
numbers.push(result);
}
if (chkfun(rpn[h])==1) //Se c'è un carattere che corrisponde a una funzione:
{
/*La funzione 'Fun', dato un carattere
*corrispondente a una funzione e un valore
*float, ne calcola la funzione corrispondente.*/
result=Fun(rpn[h],numbers.top()); //Fun è dichiarata in 'funzioni.h'
numbers.pop();
numbers.push(result);
}
if (chkop==0) //Se nell'espressione non vi è alcun operatore, allora vi deve essere un solo numero, perciò lo si associa a result
//infatti chkop si incrementa se il carattere è un operatore(vedi sopra)
result= numbers.top();
}
return result;
}
//Calcola RPN
string FoundRPN(char in[])
{
string rpn="";
stack <char> operators; //Dichiaro stack che conterrà gli operatori:
/*****************************************************************************/
//CONVERTO LA STRINGA IN NOTAZIONE INFISSA IN RPN
int h=0;
for (h=0;h<=99;h++)
{
/* Se il carattere e' un numero, questo viene aggiunto alla fine
* della stringa di output. Se il prossimo carattere non e' un
* numero, viene aggiunto il simbolo di spazio per la migliore
* leggibilita' dell'espressione in output */
if (chkchar(in[h])==1)
{
rpn+=in[h];
if ((!isdigit(in[h + 1]))&&(in[h+1]!='.')&&(in[h+1]!=','))
{
rpn+=" ";
}
if ((in[h+1]=='.')||(in[h+1]==','))
{
rpn+=".";
}
}
/* Il carattere letto e' un operatore.
* Se lo stack per gli operatori e' vuoto o il carattere
* precedente era la parentesi aperta o l'operatore letto ha
* una precedenza minore rispetto a quella dell'operatore inserito
* prima, l'operatore letto viene inserito normalmente nello stack.
* Altrimenti se l'operatore letto ha una precedenza maggiore
* rispetto a quella dell'operatore inserito prima, dallo stack
* viene tolto l'operatore con la precedenza maggiore e viene messo
* nella stringa di output. */
if (chkchar(in[h])==2)
{
bool usc=false;
while (usc==false)
{
if ((operators.empty())||(operators.top()=='(')||(precedence(in[h],operators.top())))
{
if ((chkchar(in[h-1])==1)||(in[h-1]==')'))
operators.push(in[h]);
usc=true;
}
else if (!precedence(in[h], operators.top()))
{
rpn+=operators.top();
rpn +=" ";
operators.pop();
}
}
}
/* Se il carattere è la s, il successivo è la i e quello ancora è la n, allora c'è la funzione sin: ecc.....
La funzione 'charfun': data una serie di tre caratteri, se corrispondono a una funzione, copia il carattere corrispondente
alla funzione nello stack*/
char chf=charfun(in[h],in[h+1],in[h+2]);
if (chf!=0)
operators.push(chf);
/* Se il carattere letto e' una parentesi aperta, questa viene
* messa nello stack.
* Se e' una parentesi chiusa, vuol dire che tutti gli operatori
* rimasti nello stack fino alla parentesi aperta vanno copiati nella
* stringa di output. La parentesi aperta viene cancellata dallo stack
* e dopo si contunua a leggere la stringa di input */
if (in[h]=='(')
{
operators.push(in[h]);
}
/*Se il carattere è il meno e precedentemente non vi è alcun valore, vuol dire che si intende
*il negartivo di un valore es:-5, allora sostituisco al '-' ----> '0-' */
if ((in[h]=='-')&&(chkchar(in[h-1])!=1))
{
rpn+='0';
rpn+=' ';
operators.push('-');
}
if(in[h] == ')')
{
while(operators.top() != '(') //In pratica scorre nello stack verso sinistra copiando gli operatori incontrati.
{
rpn+=operators.top();
rpn+=" ";
operators.pop();
}
operators.pop(); //Cancella la parentesi aperta
}
}
/* Tutti gli operatori rimasti nello stack vanno copiati nella
stringa di output e poi cancellati dallo stack */
while(!operators.empty())
{
rpn+=operators.top();
rpn+=" ";
operators.pop();
}
//////////////////Eventuale break point per verificare rpn.
rpn+=" ";
return rpn;
}