Tính một biểu thức số học (JavaScript code)

1+1 = ?
12*(16-(6-40/20)-7) + 5*(23-3*(7-2)) = ?
122*(4-9/(12-9))+4*-25/(425/25-9)-7 = ?
sin[(5*(13-7)- (5*6-9)*2)+pow[2,3]*(sqrt[9]-8+12*cos[23])]-log[4] = ?

File CalcuExp.js

/**
    Author: Katatunix
 **/

var FUNCTION_LIST = new Array(
    "abs", "sqrt", "sin", "cos", "tan", "cotan", "log", "exp", "pow"
);

var PARAMETER_NUMBER = new Array(
        1,      1,     1,     1,     1,       1,     1,     1,     2
);

function calculate(expr) {
	expr = expr.trim();
    if (expr.length == 0) {
		return null;
	}

    var sepa = findSeparator(expr);

    if (sepa == -1)
        return calcuSingleExp(expr);

    if (sepa == 0) {
        var ch = expr.charAt(0);
        if (ch != '+' && ch != '-') return null;
        var res = calculate(expr.substring(1));
        if (res == null) return null;
        if (ch == '-') res = -res;
        return res;
    }

    var part1 = calculate(expr.substring(0, sepa));
    if (part1 == null) {
		return null;
	}

    var part2 = calculate(expr.substring(sepa + 1));
    if (part2 == null) {
		return null;
	}

    switch (expr.charAt(sepa)) {
        case '+':
            return part1 + part2;
        case '-':
            return part1 - part2;
        case '*':
            return part1 * part2;
        default:
            return part1 / part2;
    }
}

function calcuSingleExp(expr) {
    expr = myTrim(expr);
    var len = expr.length;
    if (len == 0) return null;

    if (expr.charAt(len - 1) == ')') {
        if (len < 3 || findOpen(expr, len - 1) != 0)
            return null;
        return calculate(expr.substring(1, len - 1));
    }

    var res = convert(expr);
    if (res != null) return res;

    if (expr.charAt(len - 1) != ']') return null;
    var myopen = findOpen(expr, len - 1);
    if (myopen == -1) return null;
    var func = myTrim(expr.substring(0, myopen));

    expr = expr.substring(myopen + 1, len - 1);
    var mysub = splitByComma(expr);
    if (mysub == null) return null;

    var funcIndex = findIndexOfFunction(func);
    if (funcIndex == -1) return null;
    if (mysub.length != PARAMETER_NUMBER[funcIndex]) return null;

    res = calculate(mysub[0]);
    if (res == null) return null;

    switch (funcIndex) {
        case 0: return Math.abs(res);
        case 1: return Math.sqrt(res);
        case 2: return Math.sin(res);
        case 3: return Math.cos(res);
        case 4: return Math.tan(res);
        case 5: return 1.0 / Math.tan(res);
        case 6: return Math.log(res);
        case 7: return Math.exp(res);
        default: {
            var other = calculate(mysub[1]);
            if (other == null) return null;
            return Math.pow(res, other);
        }
    }
}

function findIndexOfFunction(func) {
    func = func.toLowerCase();
    for (var i = 0; i < FUNCTION_LIST.length; i++)
        if (FUNCTION_LIST[i] == func)
            return i;
    return -1;
}

function splitByComma(listExp) {
    listExp = myTrim(listExp);

    var len = listExp.length;
    if (listExp.charAt(0) == ',' || listExp.charAt(len - 1) == ',')
        return null;

    listSub = new Array;
    var ch, i, j = len;

    for (i = len - 1; i >= 0; i--) {
        ch = listExp.charAt(i);
        if (ch == ')' || ch == ']') {
            i = findOpen(listExp, i);
            if (i == -1) return null;
        } else if (ch == ',') {
            listSub.push(listExp.substring(i + 1, j));
            j = i;
        }
    }
    listSub.push(listExp.substring(0, j));

    i = 0; j = listSub.length - 1;
    while (i < j) {
        ch = listSub[i]; listSub[i] = listSub[j]; listSub[j] = ch;
        i++; j--;
    }

    return listSub;
}

function findSeparator(expr) {
    var len = expr.length;
    if (isOperator(expr.charAt(len - 1)))
        return null;

    var i, j = -1, ch;
    for (i = len - 1; i >= 0; i--) {
        ch = expr.charAt(i);
        if (ch == ')' || ch == ']') {
            i = findOpen(expr, i);
            if (i == -1) return -1;
        } else if (ch == '+' || ch == '-') {
            return i;
        } else if (ch == '*' || ch == '/') {
            if (j == -1) j = i;
        }
    }
    return j;
}

function isOperator(ch) {
    return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}

function findOpen(expr, off) {
    var count = 0;
    var myclose = expr.charAt(off);
    var myopen = myclose == ')' ? '(' : '[';
    while (off >= 0) {
        if (expr.charAt(off) == myclose) {
            count++;
        } else if (expr.charAt(off) == myopen) {
            count--;
            if (count == 0) return off;
        }
        off--;
    }
    return -1;
}

function myTrim(str) {
    var len = str.length;
    if (len == 0) return "";

    var l = 0;
    while (l < len) {
        if (str.charAt(l) != ' ') break;
        l++;
    }
    if (l == len) return "";

    var r = len - 1;
    while (r >= 0) {
        if (str.charAt(r) != ' ') break;
        r--;
    }

    return str.substring(l, r + 1);
}

function convert(str) {
    var num = Number(str);
    if (isNaN(num)) return null;
    if (str.indexOf("e") != -1) return null;
    return num;
}

File CalcuExp.html

<html>
<head>
<title>Tính biểu thức số học (c) Katatunix</title>
</head>

<body>
<script type="text/javascript" src="CalcuExp.js"></script>

<script type="text/javascript">
function Calculate()
{
	var inputExp = document.getElementById("ExpTxt").value;
	document.getElementById("ResTxt").value = calculate(inputExp);
}
</script>

<h2 style="font-family: arial">Tính biểu thức số học (c) Katatunix</h2>

<p>
	<textarea type="text" id="ExpTxt" cols="50" rows="10" style="font-size: 14pt"></textarea>
</p>
<p>
<input type="button" value="Tính" onclick="Calculate()" style="font-size: 14pt" />
</p>

<h4 style="font-family: arial">Kết quả</h4>
<p>
	<input type="text" id="ResTxt" size="50" readonly="true" style="font-size: 14pt" />
</p>

</body>

</html>

Or download here

Advertisements

2 thoughts on “Tính một biểu thức số học (JavaScript code)

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