User:Tyilo/calc.js

function calculate(string, angle) {	var angleModifier; switch(angle) {		case 'degrees': angleModifier = 180 / Math.PI; break; case 'radians': default: angleModifier = 1; }	var num = 0; var numbers = new Array; var operators = new Array; if(length(string.match(/[(]/g)) != length(string.match(/[)]/g))) {		return 'NaN'; }	string = string.replace(/[p][i]/g, Math.PI).replace(/[e]/g, Math.E); while(string.indexOf('(') != -1)	{		var sub1 = string.match(/[(][^]*[)]/)[0];		var sub2 = string.match(/[a-zA-Z][a-zA-Z0-9]*[(][^]*[)]/);		if(sub2 == null)		{			sub2 = sub1;		}		else		{			sub2 = sub2[0];		}		var result = calculate(sub1.substr(1, sub1.length - 2), angle);		var func = sub2.match(/[a-z0-9√]*/)[0].toLowerCase;		switch(func)		{			case 'sqrt':				result = Math.sqrt(result);				break;			case 'sin':				result = Math.sin(result / angleModifier);				break;			case 'cos':				result = Math.cos(result / angleModifier);				break;			case 'tan':				result = Math.tan(result / angleModifier);				break;			case 'asin':				result = Math.asin(result) * angleModifier;				break;			case 'acos':				result = Math.acos(result) * angleModifier;				break;			case 'atan':				result = Math.atan(result) * angleModifier;				break;			case 'log10':				result = Math.log(result) / Math.log(2);				break; case 'log10': result = Math.log(result) / Math.log(10); break; case 'ln': result = Math.log(result); break; case 'exp': result = Math.exp(result); break; default: }		string = string.replace(sub2, result); }	var match = string.match(/(Infinity)?[0-9.]*[!]/g); for(i = 0; i < length(match); i++) {		string = string.replace(match[i], factorial(Number(match[i].substr(0, match[i].length - 1)))); }	for(i = 0; i < string.length; i++) {		if(string.substr(i, 3) == 'mod' || string.substr(i, 3) == 'nPr' || string.substr(i, 3) == 'nCr') {			operators.push(string.substr(i, 3)); num = 0; i += 2; }		else if(string.substr(i, 5) == 'xroot') {			operators.push(string.substr(i, 5)); num = 0; i += 4; }		else if(string.substr(i, 8) == 'Infinity') {			if(num) {				numbers[numbers.length - 1] += 'Infinity'; }			else {				numbers.push('Infinity'); num = 1; }			i += 7; }		else if(string.charAt(i) == Number(string.charAt(i)) || string.charAt(i) == '.') {			if(num) {				numbers[numbers.length - 1] += string.charAt(i); }			else {				numbers.push(string.charAt(i)); num = 1; }		}		else {			if(!num && string.charAt(i) == '-') {				numbers.push('-'); num = 1; }			else if(string.charAt(i) == '∞') {				if(num) {					numbers[numbers.length - 1] += 'Infinity'; }				else {					numbers.push('Infinity'); num = 1; }			}			else if(num) {				operators.push(string.charAt(i)); num = 0; }		}	}	for(i = 0; i < operators.length; i++) {		if(operators[i] == '^') {			numbers[i] = Math.pow(Number(numbers[i]), Number(numbers[i + 1])); numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }		if(operators[i] == 'xroot') {			numbers[i] = Math.pow(Number(numbers[i + 1]), 1 / Number(numbers[i])); numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }		if(operators[i] == 'E') {			numbers[i] = Number(numbers[i]) + 'e' + Number(numbers[i + 1]); numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }	}	for(i = 0; i < operators.length; i++) {		if(operators[i] == '*') {			numbers[i] = Number(numbers[i]) * Number(numbers[i + 1]); numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }		if(operators[i] == '/') {			numbers[i] = Number(numbers[i]) / Number(numbers[i + 1]); numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }		if(operators[i] == 'mod') {			numbers[i] = Number(numbers[i]) % Number(numbers[i + 1]); numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }		if(operators[i] == 'nPr' || operators[i] == 'nCr') {			if(Number(numbers[i]) != Math.floor(Number(numbers[i])) || Number(numbers[i + 1]) != Math.floor(Number(numbers[i + 1])) || Number(numbers[i]) < Number(numbers[i + 1]) || Number(numbers[i]) < 0 || Number(numbers[i + 1]) < 0) {				return 'NaN'; }			else if(operators[i] == 'nPr') {				numbers[i] = factorial(Number(numbers[i])) / Math.max((Number(numbers[i]) - Number(numbers[i + 1])), 1); }			else if(operators[i] == 'nCr') {				numbers[i] = factorial(Number(numbers[i])) / (Number(numbers[i + 1]) * factorial(Number(numbers[i]) - Number(numbers[i + 1]))); }			numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }	}	for(i = 0; i < operators.length; i++) {		if(operators[i] == '+') {			numbers[i] = Number(numbers[i]) + Number(numbers[i + 1]); numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }		if(operators[i] == '-') {			numbers[i] = Number(numbers[i]) - Number(numbers[i + 1]); numbers.splice(i + 1, 1); operators.splice(i, 1); i--; }	}	return Number(numbers[0]); } function factorial(num) {	if(num == 'Infinity') {		return 'Infinity'; }	else if(Number(num) != Math.floor(num) || Number(num) < 0) {		return 'NaN'; }	else {		var result = 1; for(var i = 1; i <= num; i++) {			result *= i;		} return result; } } function length(array) {	if(array) {		return array.length; }	else {		return 0; } }