Sir, i have a numerical method project. I want to be different, so i try to make a program that can read user input, ex : sin(x+3)^(x*3^x), and find the root of the equation. I already implemented Reverse Polish Notation, and also shunting-yard algorithm. But, i found out that all my friends focused on the design, not about the advanced code. So, i want to make my code better by giving a graphic represented the function. I have an idea, with drawing each node of each value of x, with minimal range of x compared to the size of screen. The problem is, i don't know how to draw in c++. I want to add some GUI, and I also don't know how to do it.
Here is my work to prove that i have try. Sorry for the comments, i wrote in bahasa Indonesia.
#include<iostream>
#include<math.h>
#include<string.h>
#include<iomanip>
using namespace std;
string post[100]; //menampung bentuk postfix dari fungsi yang diinput user
int ukuranPost=0; //banyak sel post yang terisi
double shunting(double); //shunting-yard algorithm
void postfix(string); //mengubah infix menjadi postfix
double convert(string); //mengubah angka dalam string menjadi angka dalam double
double satuOperand(string,double); //operasi aritmatik dengan 1 operand
double duaOperand(string,double,double); //operasi aritmatik dengan 2 operand
void bisection(double); //metode bisection
void falsePosition(double); //metode false position
void secant(double); //secant methods
double convert(string inputnya)
{
int start=inputnya.length();
double total=0;
for (int i=0;i<inputnya.length();i++)
{
if(inputnya[i]=='.')
start=i;
}
if(start==inputnya.length()) //tidak ada koma
{
for(int i=0;i<start;i++)
{
total+=(int(inputnya[i])-48)*pow(10,start-i-1);
}
}
else
{
for(int i=0;i<start;i++)
{
total+=(int(inputnya[i])-48)*pow(10,start-i-1);
}
for(int i=start+1;i<inputnya.length();i++)
{
total+=(int(inputnya[i])-48)*pow(10,start-i);
}
}
return total;
}
double satuOperand(string operatorr,double operand)
{
if (operatorr=="sin")
return sin(operand);
else if (operatorr=="cos")
return cos(operand);
else if (operatorr=="tan")
return tan(operand);
else if (operatorr=="log")
return log10(operand);
else if (operatorr=="ln")
return log(operand);
}
double duaOperand(string operatorr, double operand1, double operand2)
{
if (operatorr=="+")
return (operand1+operand2);
else if (operatorr=="-")
return (operand1-operand2);
else if (operatorr=="*")
return (operand1*operand2);
else if (operatorr=="/")
return (operand1/operand2);
else if (operatorr=="^")
return (pow(operand1,operand2));
}
int prioritas(string operatorr)
{
if (operatorr=="sin" || operatorr=="cos" || operatorr=="tan" || operatorr=="log" || operatorr=="ln")
return 1;
else if (operatorr=="^")
return 2;
else if (operatorr=="*" || operatorr=="/")
return 3;
else if (operatorr=="+" || operatorr=="-")
return 4;
else
{
//tidak mungkin terjadi, karena asumsi tidak ada error handling
}
}
void postfix(string input)
{
string stack[100];
int flagPost=0;
int flagStack=0;
for (int i=0;i<input.length();i++)
{
int mark=i;
if (isdigit(input[i]))
{
while(isdigit(input[i+1]) || input[i+1]=='.')
{
i++;
}
post[flagPost]=input.substr(mark,i-mark+1);
flagPost++;
}
else if(input[i]=='-' && i==0 || input[i]=='-' && !isdigit(input[i-1]) && input[i-1]!='x' && input[i-1]!=')')
{
input=input.substr(0,i)+"(0-1)*"+input.substr(i+1);
i--;
}
else if(input[i]=='x')
{
post[flagPost]="x";
flagPost++;
}
else if(input[i]=='(')
{
stack[flagStack]="(";
flagStack++;
}
else if(input[i]==')')
{
while (stack[flagStack-1]!="(")
{
post[flagPost]=stack[flagStack-1];
flagPost++;
flagStack--;
}
if(flagStack>0)
flagStack--;
}
else
{
if (!isalpha(input[i]))
{
//bengong
}
else
{
while(!isdigit(input[i+1]) && input[i+1]!='x' && input[i+1]!='(')
{
i++;
}
}
string tmp = input.substr(mark,i-mark+1);
//push ke stack operator
if (flagStack==0 || stack[flagStack-1]=="(") //stack kosong, langsung push
{
stack[flagStack]=tmp;
flagStack++; //flag top stack
}
/* else if(flagStack!=0 && stack[flagStack-1]=="(") // langsung push kalo ketemu kurung buka
{
stack[flagStack]=tmp;
flagStack++;
}
*/
else
{ //prioritas diperhatikan
int stackOpTrakir = prioritas(stack[flagStack-1]); //priortitas top stack
while (prioritas(tmp)>=stackOpTrakir && stack[flagStack-1]!="(")
{
post[flagPost]=stack[flagStack-1];
flagPost++;
flagStack--;
if(flagStack==0)
break;
else
stackOpTrakir = prioritas(stack[flagStack-1]);
}
stack[flagStack]=input.substr(mark,i-mark+1);
flagStack++;
}
}
//cout<<"iterasi "<<i<<endl;
//cout<<"post : ";
//for (int b=0;b<flagPost;b++)
// cout<<post[b]<<" ";
//cout<<endl;
//cout<<"stack : ";
//for (int b=0;b<flagStack;b++)
// cout<<stack[b]<<" ";
//cout<<endl<<endl;
}
for (int i=flagStack-1;i>=0;i--)
{
post[flagPost]=stack[i];
flagPost++;
}
cout<<endl;
//block ini berguna untuk memeriksa hasil postfix
//for (int a=0;a<flagPost;a++)
//{
// cout<<post[a]<<endl;
//}
//menghitung berapa isi sel post yang terpakai
//berguna pada fungsi int shunting di bawah
while(post[ukuranPost]!="")
{
ukuranPost++;
}
}
double shunting(double x)
{
double tmp[100];
int flagTmp=0;
//flagTmp menunjuk ke sel yang akan diisi
//flagStack dan flagPost menunjuk ke sel yang akan diisi
for (int i=0;i<ukuranPost;i++)
{
if (isdigit(post[i][0]))
{
//ubah menjadi integer //masukan ke stack tmp;
tmp[flagTmp]=convert(post[i]);
flagTmp++;
}
else if(post[i]=="x")
{
//post int x ke stack tmp;
tmp[flagTmp]=x;
flagTmp++;
}
else
{
//bagian2 operator
if(post[i]=="sin" || post[i]=="cos" || post[i]=="tan" || post[i]=="log" || post[i]=="ln")
{ //1 operand
tmp[flagTmp-1]=satuOperand(post[i],tmp[flagTmp-1]);
}
else
{
tmp[flagTmp-2]=duaOperand(post[i],tmp[flagTmp-2],tmp[flagTmp-1]);
flagTmp--;
}
}
}
return tmp[0];
}
void bisection(double es)
{
double ea=100; //approximation error
int iterasi=0; //menghitung berapa iterasi yang diperlukan
//Bagian ini adalah bisection
cout<<"\n\nMetode pertama : Bisection\n";
double xl,xr,xm; //xl adalah x left, xr adalah x right, dan xm adalah x mid
cout<<"Masukkan nilai x kiri : ";
cin>>xl;
cout<<"Masukkan nilai x kanan : ";
cin>>xr;
double fxl,fxr,fxm; //f(xl),f(xr),f(xm)
fxl=shunting(xl);
fxr=shunting(xr);
cout<<fxl<<" "<<fxr<<endl;
while(fxl*fxr>=0)
{
if(fxl==0)
{
cout<<"Akarnya adalah "<<xl<<endl;
cout<<"Jadi, kita tidak perlu menghitung lagi."<<endl;
goto bisectionoff;
}
else if (fxr==0)
{
cout<<"Akarnya adalah "<<xr<<endl;
cout<<"Jadi, kita tidak perlu menghitung lagi."<<endl;
goto bisectionoff;
}
else if (xl==xr)
{
cout<<"Input xl dan xr dengan angka yang berbeda, harap diulangi.\n";
cout<<"Masukkan nilai x kiri : ";
cin>>xl;
cout<<"Masukkan nilai x kanan : ";
cin>>xr;
fxl=shunting(xl);
fxr=shunting(xr);
}
else
{
cout<<"Tidak ada akar di antara "<<xl<<" dan "<<xr<<endl;
cout<<"Coba ulangi dengan kombinasi xl dan xr yang berbeda.\n";
cout<<"Masukkan nilai x kiri : ";
cin>>xl;
cout<<"Masukkan nilai x kanan : ";
cin>>xr;
fxl=shunting(xl);
fxr=shunting(xr);
}
}
//sampai sini input f(xl)*f(xr) sudah lebih kecil dari nol. Inisialisasi selesai.
double tampung; //menampung xm pada iterasi sebelumnya.
printf("%-11s %-11s %-11s %-11s %-11s %-11s %-11s\n","xl","xm","xr","f(xl)","f(xm)","f(xr)","ea");
while(ea>es)
{
iterasi++;
xm=(xl+xr)/2;
if(iterasi>1)
{
ea=fabs((xm-tampung)/xm)*100;
}
fxm=shunting(xm);
printf("%-11f %-11f %-11f %-11f %-11f %-11f %-11f\n",xl,xm,xr,fxl,fxm,fxr,ea);
if(fxl*fxm<0)
{
xr=xm;
fxr=shunting(xr);
}
else
{
xl=xm;
fxl=shunting(xl);
}
tampung=xm;
}
cout<<"Akarnya adalah : "<<xm<<" dan ditemukan pada iterasi ke-"<<iterasi<<endl;
bisectionoff:
;
}
void falsePosition(double es)
{
double ea=100; //approximation error
int iterasi=0; //menghitung berapa iterasi yang diperlukan
//Bagian ini adalah bisection
cout<<"\n\nMetode kedua : False Position\n";
double xl,xr,xm; //xl adalah x left, xr adalah x right, dan xm adalah x mid
ulangfalse: ;
ea=100;
iterasi=0;
cout<<"Masukkan nilai x kiri : ";
cin>>xl;
cout<<"Masukkan nilai x kanan : ";
cin>>xr;
double fxl,fxr,fxm; //f(xl),f(xr),f(xm)
fxl=shunting(xl);
fxr=shunting(xr);
while(fxl*fxr>=0)
{
if(fxl==0)
{
cout<<"Akarnya adalah "<<xl<<endl;
cout<<"Jadi, kita tidak perlu menghitung lagi."<<endl;
goto falseoff;
}
else if (fxr==0)
{
cout<<"Akarnya adalah "<<xr<<endl;
cout<<"Jadi, kita tidak perlu menghitung lagi."<<endl;
goto falseoff;
}
else if (xl==xr)
{
cout<<"Input xl dan xr dengan angka yang berbeda, harap diulangi.\n";
cout<<"Masukkan nilai x kiri : ";
cin>>xl;
cout<<"Masukkan nilai x kanan : ";
cin>>xr;
fxl=shunting(xl);
fxr=shunting(xr);
}
else
{
cout<<"Tidak ada akar di antara "<<xl<<" dan "<<xr<<endl;
cout<<"Coba ulangi dengan kombinasi xl dan xr yang berbeda.\n";
cout<<"Masukkan nilai x kiri : ";
cin>>xl;
cout<<"Masukkan nilai x kanan : ";
cin>>xr;
fxl=shunting(xl);
fxr=shunting(xr);
}
}
//sampai sini input f(xl)*f(xr) sudah lebih kecil dari nol. Inisialisasi selesai.
double tampung; //menampung xm pada iterasi sebelumnya.
printf("%-11s %-11s %-11s %-11s %-11s %-11s %-11s\n","xl","xm","xr","f(xl)","f(xm)","f(xr)","ea");
while(ea>es)
{
iterasi++;
xm=xr-fxr*(xl-xr)/(fxl-fxr);
if(iterasi>1)
{
ea=fabs((xm-tampung)/xm)*100;
}
fxm=shunting(xm);
printf("%-11f %-11f %-11f %-11f %-11f %-11f %-11f\n",xl,xm,xr,fxl,fxm,fxr,ea);
if(fxl*fxm<0)
{
xr=xm;
fxr=shunting(xr);
}
else
{
xl=xm;
fxl=shunting(xl);
}
tampung=xm;
if(iterasi==5000)
{
cout<<"Kombinasi xl dan xr ini tidak memungkinkan kita memperoleh akarnya.\n";
cout<<"Coba ulangi dengan kombinasi xl dan xr yang berbeda.\n";
goto ulangfalse;
}
}
cout<<"Akarnya adalah : "<<xm<<" dan ditemukan pada iterasi ke-"<<iterasi<<endl;
falseoff:
;
}
void secant(double es)
{
double ea=100; //approximation error
int iterasi=0; //menghitung berapa iterasi yang diperlukan
//Bagian ini adalah secant methods
cout<<"\n\nMetode ketiga : Secant Methods\n";
double x1,x2,x3; //xl adalah x left, xr adalah x right, dan xm adalah x mid
cout<<"Masukkan dua buah nilai x untuk inisialisasi.\n";
ulangsecant:
;
ea=100;
iterasi=0;
cout<<"x1 = "; cin>>x1;
cout<<"x2 = "; cin>>x2;
double fx1,fx2,fx3; //f(xl),f(xr),f(xm)
fx1=shunting(x1);
fx2=shunting(x2);
while(fx1==0 ||fx2==0 || x1==x2)
{
if(fx1==0)
{
cout<<"Akarnya adalah "<<x1<<endl;
cout<<"Jadi, kita tidak perlu menghitung lagi."<<endl;
goto secantoff;
}
else if (fx2==0)
{
cout<<"Akarnya adalah "<<x2<<endl;
cout<<"Jadi, kita tidak perlu menghitung lagi."<<endl;
goto secantoff;
}
else if (x1==x2)
{
cout<<"Input x1 dan x2 dengan angka yang berbeda, harap diulangi.\n";
cout<<"Masukkan nilai x1 : ";
cin>>x1;
cout<<"Masukkan nilai x2 : ";
cin>>x2;
fx1=shunting(x1);
fx2=shunting(x2);
}
}
//sampai sini input f(xl)*f(xr) sudah lebih kecil dari nol. Inisialisasi selesai.
printf("%-11s %-11s %-11s %-11s %-11s %-11s %-11s\n","x1","x2","x3","f(x1)","f(x2)","f(x3)","ea");
while(ea>es)
{
iterasi++;
x3=x2-fx2*(x1-x2)/(fx1-fx2);
if(iterasi>1)
{
ea=fabs((x3-x2)/x3)*100;
}
fx3=shunting(x3);
printf("%-11f %-11f %-11f %-11f %-11f %-11f %-11f\n",x1,x2,x3,fx1,fx2,fx3,ea);
x1=x2;
x2=x3;
fx1=shunting(x1);
fx2=shunting(x2);
if(iterasi==5000)
{
cout<<"Tidak ada akar yang bisa ditemukan dengan kombinasi x1 dan x2 ini.\n";
cout<<"Coba masukkan kombinasi yang lain.\n";
goto ulangsecant;
}
}
cout<<"Akarnya adalah : "<<x3<<" dan ditemukan pada iterasi ke-"<<iterasi<<endl;
secantoff:
;
}
int main()
{
string input;
cout<<"\t\tSelamat Datang di Program Penarikan Akar Secara Numerik\n\n";
cout<<"Masukkan fungsi dalam x yang hendak dicari akarnya.\nJangan lupa membaca petunjuk pada laporan."<<endl;
cout<<"Fungsi : ";
cin>>input; //infix
postfix(input); //mengubah input menjadi postfix
double s; //s adalah jumlah bilangan signifikan yang diinginkan
double es; //prespecified error
cout<<"Masukkan jumlah bilangan signifikan yang diinginkan : ";
cin>>s;
es=0.5*pow(10,2-s);
//mengerjakan bagian bisection
bisection(es);
//mengerjakan bagian false position
falsePosition(es);
//mengerjakan bagian secant
secant(es);
cin>>input;
return 0;
}
thanks sir for your help.