Просмотр полной версии : как пропарсить строку "34/6-(4+1)*(2+1.5)" ?
Задача: нужно получить результат математического выражения, заключенного в строку. Пример "34/6-(4+1)*(2+1.5)".
В ActionScript'e есть ф-ция eval(), но она делает совсем не то.
Может, есть какие-то альтернативы? Ато я уже собрался вручную парсить...
альтернатива == ручками
не забудь показать творение =)
YuriiZelenev
17.12.2003, 14:15
dolgo promuchieshsya...
Math.Expression = function() {}
Math.Expression.prototype.operators="+-*/^(";
Math.Expression.prototype.opPriority=[["^"],["neg"],["*","/"],["+","-"]];
Math.Expression.prototype.functions=["abs","acos","asin","atan","ceil","cos","exp","floor","log","random","round","sin","sqrt","tan"];
Math.Expression.prototype.parse = function(str,link) {
var pos=0;
var operator,bracket,len;
if (arguments.length<2) {
this.parts=new Array();
link=this.parts;
}
while ((operator=this.findOperator(str,pos)).pos!=-1) {
if (pos<operator.pos) {
len=link.length;
link[len]=new Object();
link[len].type="variable";
link[len].value=str.substring(pos,operator.pos);
if (!isNaN(Number(link[len].value))) {
link[len].type="value";
link[len].value=Number(link[len].value);
}
}
if (operator.op!="(") {
len=link.length;
link[len]=new Object();
link[len].type="operator";
if (link[len-1].type=="operator" || len==0) {
if (operator.op=="-") link[len].value="neg";
else return false;
}
else link[len].value=operator.op;
link[len].priority=this.findPriority(link[len].value);
pos=operator.pos+1;
}
else {
bracket=this.findBracket(str,operator.pos);
if (bracket==-1) return false;
len=link.length;
if (link[len-1].type=="variable") this.findFunction(link[len-1]);
link[len]=new Object();
link[len].type="expression";
link[len].value=new Array();
if (!this.parse(str.substring(operator.pos+1,bracket),link[len].value)) return false;
pos=bracket+1;
}
}
if (pos<str.length) {
len=link.length;
link[len]=new Object();
link[len].type="variable";
link[len].value=str.substring(pos);
if (!isNaN(Number(link[len].value))) {
link[len].type="value";
link[len].value=Number(link[len].value);
}
}
return true;
}
Math.Expression.prototype.findOperator = function(str,pos) {
var foundAt,foundAtTemp;
foundAt=str.length;
for (var i=0; i<this.operators.length; i++) {
foundAtTemp=str.indexOf(this.operators.charAt(i),pos);
if (foundAtTemp<foundAt && foundAtTemp!=-1) foundAt=foundAtTemp;
}
var a=new Object();
a.pos=(foundAt==str.length) ? -1 : foundAt;
a.op=str.charAt(foundAt);
return a;
}
Math.Expression.prototype.findPriority = function(op){
for (var i=0; i<this.opPriority.length; i++) {
for (var j=0; j<this.opPriority[i].length; j++) {
if (op==this.opPriority[i][j]) return i;
}
}
}
Math.Expression.prototype.findBracket = function(str,pos){
var open=pos
var close=pos;
do {
close=str.indexOf(")",close+1);
open=str.indexOf("(",open+1);
} while (close>open && open!=-1);
return close;
}
Math.Expression.prototype.findFunction = function(link){
for (var i in this.functions) {
if (link.value==this.functions[i]) link.type="function";
}
}
Math.Expression.prototype.eval = function() {
this.evaluated=new Array();
this.copyPartsArray(this.parts,this.evaluated);
return this.evalExpression(this.evaluated);
}
Math.Expression.prototype.copyPartsArray = function(link,copylink) {
for (var i in link) {
copylink[i]=new Object();
copylink[i].type=link[i].type;
copylink[i].value=link[i].value;
copylink[i].priority=link[i].priority;
if (link[i].type=="expression") {
copylink[i].value=new Array();
this.copyPartsArray(link[i].value,copylink[i].value);
}
}
}
Math.Expression.prototype.evalExpression = function(link) {
var op;
var i;
for (i in link) {
if (link[i].type=="expression") link[i].value=this.evalExpression(link[i].value);
if (link[i].type=="variable") link[i].value=this.evalVariable(link[i].value);
}
i=0;
while (i<link.length) {
if (link[i].type=="function") {
link[i].value=this.evalFunction(link[i].value,link[i+1].value);
link.splice(i+1,1);
}
i++;
}
for (var i=0; i<this.opPriority.length; i++) {
var k=0;
while (k<link.length) {
if (link[k].type=="operator" and link[k].priority==i) {
op=link[k].value;
link[k].type="value";
link[k].value=this.evalOperator(link[k].value,link[k-1].value,link[k+1].value);
link.splice(k+1,1);
if (op!="neg") link.splice(k-1,1);
k--;
}
k++;
}
}
return link[0].value;
}
Math.Expression.prototype.evalOperator = function(op,v1,v2) {
if (op=="+") return v1+v2;
if (op=="-") return v1-v2;
if (op=="*") return v1*v2;
if (op=="/") return v1/v2;
if (op=="^") return v1==0 ? 0 : Math.pow(v1,v2);
if (op=="neg") return -v2;
}
Math.Expression.prototype.evalVariable = function(v) {
return eval(v);
}
Math.Expression.prototype.evalFunction = function(func,v) {
return Math[func](v);
}
Primer://Primer
myExpression = new Math.Expression();
myExpression.parse("34/6-(4+1)*(2+1.5)");
trace(myExpression.eval());
ps:no esli sdelaesh luchshe - pokajesh...
dlya poiska: toNumber to number string to number stringToNumber convertToNumber
YuriiZelenev
17.12.2003, 14:30
dlya poiska:
toDigit to Digit
toNumber() stringToNumber() convertToNumber() toDigit()
toNumber(); stringToNumber(); convertToNumber(); toDigit();
sergwizard
17.12.2003, 22:56
2 YuriiZelenev
И не лениво тебе было это писать? Или у тебя уже была наработка?
Но, классно!
да, немного опоздал.... :)
Вот моё произведение:
var operators = Array(
"+", "-", "*", "/", "^"
);
function Calc(str){
//Раскрытие скобок:
var pos1 = 0;
while( pos1 || (pos1 = str.indexOf("(")) != -1){
var pos2 = str.indexOf(")",++pos1);
if(pos2>0){
var noBrackets = str.substring(pos1,pos2);
pos1 = str.indexOf("(",pos1);
if(pos1 > pos2 || pos1 < 0){
str = str.split("("+noBrackets+")").join( Calc_noBrackets(noBrackets,0) );
pos1 = 0;
}
}else{
trace("Error: No ending ')' !");
return;
}
}
return Calc_noBrackets(str,0);
}
function Calc_noBrackets(str,opId){
str = str.split("--").join("+");
str = str.split("+-").join("-");
var args = str.split(operators[opId]);
var result = 0;
for(var argId=0;argId<args.length;argId++){
var arg = args[argId];
for(var nextOpId=opId+1;nextOpId<operators.length;nextOpId++)
if(arg.indexOf(operators[nextOpId])>0){
arg = Calc_noBrackets(arg,nextOpId);
break;
}
arg = new Number(arg);
if(argId==0)
result = arg;
else switch(operators[opId]){
case "^": result = Math.pow(result,arg); break;
case "*": result *= arg; break;
case "/": result /= arg; break;
case "+": result += arg; break;
case "-": result -= arg; break;
}
}
return result;
}
Пример:
trace( Calc("34/6-(4+1)*(2+1.5)") )
начинающий
15.01.2004, 14:40
Если флешка будет запускаться не из браузера, то дальше можете не читать!
Не мудрствуя лукаво, предлагаю использовать уже имеющееся средство в движке JScript, а не заниматься изобретением велосипеда:
var str2Parse = "34/6-(4+1)*(2+1.5)";
getURL("javascript: calcDemo.setVariable('result', eval('"+str2Parse+"'))");
_root.onEnterFrame = function() // waiting for browser’s respond
{
if(result != undefined)
{
_root.tf.text = str2Parse + " = " + result;
delete _root.onEnterFrame;
}
}
Запустите НТМ-льку из примера - SWF-ку самостоятельно запускать не стОит!
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.