Last active
August 29, 2015 14:03
-
-
Save martinusadyh/8f7a9c77825474aef483 to your computer and use it in GitHub Desktop.
Implementasi Shunting-Yard Algorithm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Implementasi custom calculator dengan menggunakan algoritma Shunting-Yard | |
// Referensi Algoritma : http://en.wikipedia.org/wiki/Shunting-yard_algorithm | |
// Contoh : http://www.chris-j.co.uk/parsing.php | |
// Custom calculator untuk melakukan conversi rumus menjadi nilai akhir | |
// @param String rumus: Informasi tentang rumus yang ingin dihitung. | |
// Contoh rumus adalah : | |
// - a+b*c | |
// - ((a+b)*c*d/(e+f)) | |
// - a/b/c*d | |
// | |
// @param Object object: Informasi object dengan property-property yang tertulis | |
// pada rumus. Contoh : | |
// var obj = { | |
// a: 11, | |
// b: 12, | |
// c: 13, | |
// d: 2, | |
// e: 11, | |
// f: 2 | |
// }; | |
// | |
// Contoh cara penggunaan : | |
// Rumus : ((a+b)*c*d/(e+f)) | |
// Object: | |
// var obj = { | |
// a: 11, | |
// b: 12, | |
// c: 13, | |
// d: 2, | |
// e: 11, | |
// f: 2 | |
// }; | |
// Penggunaan : hitung("((a+b)*c*d/(e+f))", obj); | |
// | |
// @return nilai object BigDecimal | |
function hitung(rumus, objValue) { | |
var resultAkhir; | |
var infix = new Array(); | |
var output = new Array(); | |
var token = new Array(); | |
var foundKey = false; | |
for (var i=0; i<rumus.length; i++) { | |
foundKey = false; | |
var value = null; | |
for (var key in objValue) { | |
if (rumus[i] === key) { | |
rumus.replace(rumus[i], objValue[key]); | |
value = objValue[key]; | |
foundKey = true; | |
break; | |
} | |
} | |
if (!foundKey) { | |
infix.push(rumus[i]); | |
} else { | |
infix.push(new BigDecimal(String(value))); | |
} | |
} // end for i | |
for (var i=0; i<infix.length; i++) { | |
if (typeof infix[i] === 'object') { | |
output.push(infix[i]); | |
} else { | |
switch(infix[i]) { | |
case '(': | |
token.push(infix[i]); | |
break; | |
case ')': | |
var done = true; | |
do { | |
var tmpToken = token.pop(); // ambil token terakhir | |
if (tmpToken === "(") { | |
done = false; | |
} else { | |
output.push(tmpToken); | |
} | |
} while (done); | |
break; | |
case '-': | |
var tmpToken = token.pop(); // ambil token terakhir | |
if (tmpToken === "+") { | |
output.push(tmpToken); | |
} else { | |
token.push(tmpToken); | |
} | |
token.push(infix[i]); | |
break; | |
case '+': | |
var tmpToken = token.pop(); // ambil token terakhir | |
if (tmpToken === "-") { | |
output.push(tmpToken); | |
} else { | |
token.push(tmpToken); | |
} | |
token.push(infix[i].toString()); | |
break; | |
case '*': | |
var tmpToken = token.pop(); // ambil token terakhir | |
if (tmpToken === "/") { | |
output.push(tmpToken); | |
} else { | |
token.push(tmpToken); | |
} | |
token.push(infix[i]); | |
break; | |
case '/': | |
var tmpToken = token.pop(); // ambil token terakhir | |
if (tmpToken === "*") { | |
output.push(tmpToken); | |
} else { | |
token.push(tmpToken); | |
} | |
token.push(infix[i]); | |
break; | |
default: console.log(""); | |
} | |
} | |
} // end for | |
// pengecekan stack token, jika msh ada sisa masukkan ke output | |
if (token.toString().length > 0) { | |
var isExists = true; | |
do { | |
if (token.toString().length > 0) { | |
var tmpToken = token.pop(); | |
output.push(tmpToken); | |
} else { | |
isExists = false; | |
} | |
} while(isExists); | |
} | |
if (token.toString().length === 0) { | |
// keluarin semua yang di output masukkan ke token | |
for (var i=0; i<output.length; i++) { | |
if (typeof output[i] === "object") { | |
token.push(output[i]); | |
} else { | |
switch(output[i]) { | |
case '-': | |
var valAkhir = token.pop(); | |
var valAwal = token.pop(); | |
var valFinal = valAwal.subtract(valAkhir); | |
token.push(valFinal); | |
break; | |
case '+': | |
var valAkhir = token.pop(); | |
var valAwal = token.pop(); | |
var valFinal = valAwal.add(valAkhir); | |
token.push(valFinal); | |
break; | |
case '*': | |
var valAkhir = token.pop(); | |
var valAwal = token.pop(); | |
var valFinal = valAwal.multiply(valAkhir); | |
token.push(valFinal); | |
break; | |
case '/': | |
var valAkhir = token.pop(); | |
var valAwal = token.pop(); | |
var valFinal = valAwal.divide(valAkhir, 16, 4); | |
token.push(valFinal); | |
break; | |
default: console.log(""); | |
} // end switch | |
} // end else | |
} // end for | |
} // end if token | |
for (var j=0; j<token.length; j++) { | |
if (typeof token[j] === "object") { | |
resultAkhir = token[j]; | |
} | |
} | |
return resultAkhir; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment