Pemecahan masalah penyusunan struktur tree dg contoh kasus operasi matematika(C#)

Pada operasi matematika, kita kerap kali menghadapi masalah siapa operasi yang harus didahulukan atau yg terakhir kita eksekusi, misal:  5+4^2*7

Pada operasi diatas, kita tidak bisa langsung melakukan perhitungan dari depan, misal 5+4=9, 9^2=81, dan 81*7=567. Tidak seperti itu bukan.. Untuk menghitung operasi di atas, kita harus mulai dari 4^2=16, lalu 16*7=112, dan 112+5=117….

567 dan 117, berbeda jauh bukan? dan sialnya, akan ada banyak operasi matematika yang jauh lebih kompleks dari kasus di atas. Mungkin ini bukanlah hal yang sulit bila kita hitung secara manual, tapi ini tidaklah mudah untuk kita terjemahkan ke dalam program. Maka dari itu, kita perlu menerapkan suatu teknik yang bisa mengatur pengurutan dari eksekusi suatu operasi. Teknik yang akan saya bahas disini adalah dengan menggunakan strutur pohon http://en.wikipedia.org/wiki/Tree_data_structure. Untuk memahami lebih jauh tentang tree silahkan anda pelajari sendiri, karena untuk postingan ini, saya akan berfokus pada teknik pemrogramannya, bukan konsep dari tree itu sendiri..

Baiklah, saya akan membuat sebuah contoh kasus dimana kita akan membuat program kalkulator yang dapat mengeksekusi lebih dari satu operasi dimana di dalamnya terdapat struktur tree untuk menentukan jalanny suatu operasi..
Misal kita memiliki kasus seperti beriktu:

Jelas anda tahu bukan hasilnya berapa? Yak silahkan anda hitung sendiri ^_^..

Mari kita jalannya perhitungan tersebut:

  1. 1^9…..(1), pangkat adalah operasi yang pertama kita jalankan.
  2. 5*3…..(2)
  3. 8/2…..(3)
  4. 3-2…..(4)
  5. (3)*(4)….(5)
  6. (1 )+(2)….(6)
  7. (6)+(5)… finish..

Dari kasus tersebut, hal pertama yang harus kita lakukan adalah memberi level pada masing2 operasi. Level sendiri kita gunakan untuk mengetahui siapa yang harus dikerjakan lebih dulu dan belakangan:

private int duluan(string n)

{

int antri;

if (n == “^”) antri = 3;

else if (n == “!” || n == “C” || n == “P”) antri = 4;

else if (n == “*” || n == “/”) antri = 2;

else if (n == “+” || n == “-“) antri = 1;

else antri = 0;

return antri;

}

Code diatas digunakan untuk mengenali level-level operasi yang dmasukkan. Semakin besar level yang dimilik oleh suatu operasi, maka operasi tersebut akan diutamakan dari operasi lain yang level nya lebih rendah..

Setelah itu, dalam satu kasus, tentunya kita harus mengenali mana saja yang termasuk operasi atau mana yang bukan. Misal: 7+5, dari operasi di atas, tentunya program harus tahu apakah “7” merupakan sebuah angka? atau “+” tersbut mrpkn sebuah angka atau operasi? Nah, maka dari itu kita harus kenali satu persatu, berikut pemecahan yang saya buat dari masalah tersebut:

private int operato(string i)

{

if (i == “^” || i == “*” || i == “/” || i == “+” || i == “-” || i == “!” || i == “C” || i == “P”)

return 1;

else

return 0;

}

Dari code di atas, akan dikenali apakah suatu inputan bernilai sebagai operator atau angka..

Di dalam tree, kita mengenal istilah pop dan push(silahkan pelajari lagi mengenai konsep ini). Saya akan jelaskan secara singkat, untuk melakukan pengurutan operasi, kita akan melibatkan suatu tempat penyimpanan sementara yang berbentuk array yang berguna untuk membantu kita menerapkan pengurutan operasi. Nah, “push” sendiri adalah suatu perintah dimana kita ingin menginput suatu nilai ke dalam suatu tempat penyimpanan tadi, sedangkan “pop” adalah kondisi kita ingin mengambil nilai terakhir dari suatu array dan mengeluarkannya dari tempat penyimpanan sementara tersebut. Karena ada ny nilai tempat penyimpanan tersebut, maka kita harus mendeklarasikannya ke dalam sebuah variabel array(anda bisa menggunakan tipe list<> atau yg lainnya, tapi saya contohkan dengan array):

private double[] nilai = new double[100];//variabel penyimpanan sementara

private int b;//indeks variabel nilai[]

Setelah itu, kita buat perintah push dan pop nya:

private void pushHitung(double isi)

{

b += 1;

nilai[b] = isi;

}

private double popHitung()

{

double bentar;

bentar = nilai[b];

b–;

return bentar;

}
Code di atas telah memperlihatkan bagaimana suatu nilai akan disimpan ke dalam array.

Untuk menyempurnakan aplikasi perhitungan kita, mari kita tambahkan agar tidak hanya operasi-operasi biasa yang bisa kita eksekusi, tetapi kita buat perhitungan2 seperti “sin”,”cos”,”tan”, “permutasi”, “combinasi”, dll dapat kita eksekusi juga. Untuk melakukan hal itu, pertama-tama, kita harus definisikan apa2 saja yang bisa kita eksekusi:

string[] strFunctionsdepan ={“sqrt”,”abs”, “sin”, “cos”, “tan”, “asin”,”acos”,”atan”,

“sinh”,”cosh”,”tanh”,”exp”,”ln”,”log”};

string[] strFunctionBelakang = { “!” };

string[] strFunctionDeBel = { “P”, “C” };


Operasi2 tersebut saya bagi menjadi tiga jenis, “strFunctiondepan” dimana operasi tersebut akan diletakkan di depan angka, misal cos(90), lalu ada “strFunctionBelakang” dimana operasi tersebut akan diletakkan di belakang suatu angka, misal faktorial: 5!, dan satu lagi operasi “strFunctionDeBel” dimana operasi tersebut diletakkan di antara angka yang akan akan di eksekusi, misal permutasi: 5P2.

Nah, karena kita sudah mendefinisikan beberapa penghitugan sendiri, berarti program kita juga harus bisa melakukan pengenalan terhadap operasi-operasi tersebut, mari kita buat agar program dapat mengenali penghitungan yang sudah kita definisikan tersebut:

private bool cekFungsiDepan(string isi)

{

for (int i = 0; i < strFunctionsdepan.Length; i++)

if (string.Compare(isi, strFunctionsdepan[i], true) == 0)

return true;

return false;

}

private bool cekFungsiBelakang(string isi)

{

for (int i = 0; i < strFunctionBelakang.Length; i++)

if (string.Compare(isi, strFunctionBelakang[i], true) == 0)

return true;

return false;

}

private bool cekFungsiDeBel(string isi)

{

for (int i = 0; i < strFunctionDeBel.Length; i++)

if (string.Compare(isi, strFunctionDeBel[i], true) == 0)

return true;

return false;

}

Code di atas berguna untuk mengenali fungsi yang telah kita definisikan sendiri.

Setelah kita berhasil mengenali operasi2 tersebut, mari kita buat suatu perintah yang akan mendefinisikan apa perintah yang akan dilakukan jika kita mengeksekusi program tersebut:

private double operation(string fungsi, double nilai)

{

double hasil;

switch (fungsi)

{

case “sin”:

hasil = Math.Sin(nilai);

break;

case “cos”:

hasil = Math.Cos(nilai);

break;

case “tan”:

hasil = Math.Tan(nilai);

break;

case “abs”:

hasil = Math.Abs(nilai);

break;

case “asin”:

hasil = Math.Asin(nilai);

break;

case “acos”:

hasil = Math.Acos(nilai);

break;

case “atan”:

hasil = Math.Atan(nilai);

break;

case “sinh”:

hasil = Math.Sinh(nilai);

break;

case “cosh”:

hasil = Math.Cosh(nilai);

break;

case “tanh”:

hasil = Math.Tanh(nilai);

break;

case “exp”:

hasil = Math.Exp(nilai);

break;

case “ln”:

hasil = Math.Log(nilai);

break;

case “log”:

hasil = Math.Log10(nilai);

break;

case “sqrt”:

hasil = Math.Sqrt(nilai);

break;

default:

hasil = 0;

break;

}

return hasil;

}

Setelah itu, mari kita maju ke tahap dimana input yang kita masukkan akan di urutkan terlebih dahulu berdasarkan levelnya:

private int x, y;//indeks array

private string[] stack = new string[100];//tempat menyimpan sementara

private string[] itu = new string[100];//variabel penyimpanan akhir

private string sementara = “”;//penyimpanan string berbentuk digit sementara

public ubahOrder(string isi)

{

string awal;

x = 0; y = 0;

//Membaca tiap karakter sesuai panjangnya

for (int i = 0; i < isi.Length; i++)

{

awal = isi.Substring(i, 1);

if (awal == “(“)

{

if (sementara != “”)

simpan();

push(awal);

}

else if (awal == “)”)

{

//Memasukkan angka ke dalam nilai

if (sementara != “”)

simpan();

while (stack[x] != “(“)

{

itu[y] = pop();

y += 1;

}

pop();

}

else

{

if (operato(awal) == 1)

{

while (duluan(awal) <= duluan(stack[x]) && x != 0)

{

if (sementara != “”)

simpan();

itu[y] = pop();

y += 1;

}

push(awal);

//Memasukkan angka ke dalam nilai

if (sementara != “”)

simpan();

}

else

{

sementara += awal;

}

}

}

//Memasukkan angka ke dalam nilai

if (sementara != “”)

simpan();

//Mengeluarkan nilai yang masih ada di dalam stack

if (x != 0)

{

while (x > 0 && stack[x] != “(“)

{

itu[y] = pop();

y += 1;

}

}

}

Anda melihat di dalam code di atas memanggil sebuah fungsi simpan, yang digunakan untuk menyimpan tumpukan yang baru untuk pengurutannya, mari kita buat fungsi simpan tersebut seperti beriktu:

private void simpan()

{

itu[y] = sementara;

y += 1;

sementara = “”;

}

Setelah itu selesai, mari kita buat sebuah perintah yang digunakan untuk melakukan perhitungan dari operasi yang kita masukkan:

private double hasil;//penyimpanan hasil akhir

public hitung(string[] nilai, int batas)

{

hasil = 0;

int s;

string kar;

double kiri, kanan;

b = 0;

for (s = 0; s < batas; s++)

{

kar = nilai[s];

if (kar == “^”)

{

kanan = popHitung();

kiri = popHitung();

hasil = (Math.Pow(kiri, kanan));

pushHitung(hasil);

}

else if (kar == “*”)

{

kanan = popHitung();

kiri = popHitung();

hasil = (kiri * kanan);

pushHitung(hasil);

}

else if (kar == “/”)

{

kanan = popHitung();

kiri = popHitung();

hasil = (kiri / kanan);

pushHitung(hasil);

}

else if (kar == “+”)

{

kanan = popHitung();

kiri = popHitung();

hasil = (kiri + kanan);

pushHitung(hasil);

}

else if (kar == “-“)

{

kanan = popHitung();

kiri = popHitung();

hasil = (kiri – kanan);

pushHitung(hasil);

}

else if (cekFungsiDepan(kar))

{

s += 1;

pushHitung(operation(kar, double.Parse(nilai[s])));

hasil = operation(kar, double.Parse(nilai[s]));

}

else if (cekFungsiBelakang(kar))

{

double ini = popHitung();

hasil = faktorial(ini);

pushHitung(hasil);

}

else if (cekFungsiDeBel(kar))

{

double ini = popHitung();

double itu = popHitung();

if (kar == “P”)

hasil = permutasi(itu, ini);

else if (kar == “C”)

hasil = kombinasi(itu, ini);

pushHitung(hasil);

}

else

{

pushHitung(double.Parse(kar));

hasil = double.Parse(kar);

}

}

}

Selesai, anda tinggal memasukkan text yang di input user ke kalkulator dan mengeksekusinya setelah melakukan pengurutan:

ubahOrder baru = new ubahOrder(“input dari user”);

hitung ini = new hitung(baru.getItu(), baru.getY());

textBox2.Text = ini.getHasil().ToString();

Selesai…

Hasil dari code di atas akan menjadi seperti berikut:

Bila ada yang belum jelas, anda dapat mengunduh source dari link berikut: http://sabitblog.blogspot.com/2010/08/smart-statmat.html. Disana akan ada link sebuah aplikasi open source yang dapat anda download juga source code ny…

Selamat mencoba…


Saya bukanlah seorang master, hanya seorang pelajar yg mencoba sharing isi kepalanya..

Jika ada kesalahan dari yg saya buat, mohon koreksi…

Semoga membantu…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: