[JavaScript] ÃæÃֵˡ¤Î°ì¸µ°ì¼¡ÊýÄø¼°¤ò²ò¤¯ÅÅÂî
- 2008-03-12
- ¥«¥Æ¥´¥ê: Client Side
- ¥¿¥°: JavaScript ¥Ñ¡¼¥µ ÅÅÂî ÃæÃֵˡ °ì¼¡ÊýÄø¼°ÅÅÂî
Á°²ó¤Îµ»ö¤Ç½ñ¤¤¤¿ÅÅÂî¤òȯŸ¤µ¤»¤Æ¡¢´Êñ¤Ê°ì¸µ°ì¼¡ÊýÄø¼°¤ò²ò¤¯¤³¤È¤Î¤Ç¤¤ëÅÅÂî¤Ë¤·¤Æ¤ß¤¿¡£x¤ò1¤Ä¤À¤±´Þ¤à°ì¼¡ÊýÄø¼°¤ò²ò¤¯¤³¤È¤¬¤Ç¤¤ë¡£
Îã
alert(calc('-x+1=2-3')); // 2 / 1
alert(calc('3*3/(2-x)=4+(2/3*4)+1.2')); // 101 / 118
alert(calc('(8-5)/3=1/(x+2)-1.3*0.4')); // -51 / 38
³ç¸Ì¤Èñ¹à±é»»»Ò¤ò»È¤¦¤³¤È¤¬¤Ç¤¤Þ¤¹¡£º£¤Î¤È¤³¤í¡¢x¤Ï¿ô¼°Ãæ¤Ë1¤Ä¤À¤±¤·¤«´Þ¤á¤ë¤³¤È¤¬¤Ç¤¤Þ¤»¤ó¡£
¼Âư¥µ¥ó¥×¥ë¤È¥½¡¼¥¹¥³¡¼¥É¤Ï³¤¤Ç¡£
ưºî¥µ¥ó¥×¥ë
- ¿ô¼°
- ʬ¿ô²ò
- 2 / 1
- ¾®¿ô²ò
- 2
Á°²ó¤Îµ»ö¤«¤é¤Î¼ç¤ÊÊѹ¹ÅÀ
¤Þ¤º¡¢UnaryOperation¥¯¥é¥¹¤ÈBinaryOperation¥¯¥é¥¹¤ÈFraction¥¯¥é¥¹¤ÈUnknown¥¯¥é¥¹¤Ë¡¢type¥Õ¥£¡¼¥ë¥É¤ò»ý¤¿¤»¡¢¤½¤ì¤¾¤ì'Unary', 'Binary', 'Atomic', 'Atomic'¤È¤¤¤¦Ãͤò»ý¤¿¤»¤¿¡£¤½¤·¤Æ¡¢¤³¤Îtype¥Õ¥£¡¼¥ë¥É¤ò¸«¤Ê¤¬¤é¡¢²ò¤ò·×»»¤¹¤ësolve()´Ø¿ô¤ò¢¤Î¤è¤¦¤Ë½ñ¤¤¤¿¡£
var solve = function(left, right) {
var hasLeftX = left.hasX();
if (!hasLeftX == !right.hasX()) throw 'Error'; //XXX
var variable = hasLeftX ? left : right;
var constant = (hasLeftX ? right : left).operate();
switch (variable.type) {
case 'Atomic':
return constant;
case 'Unary':
return solve(variable.operand, new UnaryOperation(variable.operator, constant));
case 'Binary':
var canceler = ({'+': '-', '-': '+', '*': '/', '/': '*'})[variable.operator];
switch (canceler) {
case '+': case '*':
return solve(variable.operand1, new BinaryOperation(canceler, variable.operand2, constant));
case '-': case '/':
return solve(variable.operand1, new BinaryOperation(canceler, constant, variable.operand2));
}
}
};
¤½¤·¤Æ¡¢À¸¤Î¿ô¼°¤ò¼õ¤±¼è¤Ã¤Æ¡¢¥Ñ¡¼¥¹¤·¤¿¸å¤Ësolve()´Ø¿ô¤ËÅϤ¹calc()´Ø¿ô¤ò¢¤Î¤è¤¦¤ËÄêµÁ¡£
function calc(source) {
var sides = source.split('=');
return solve(parse(sides[0]), parse(sides[1]));
}
solve()´Ø¿ô¤Î²òÀâ
var hasLeftX = left.hasX(); if (!hasLeftX == !right.hasX()) throw 'Error'; //XXX var variable = hasLeftX ? left : right; var constant = (hasLeftX ? right : left).operate();
ºÇ½é¤Î4¹Ô¤Ï¡¢º¸ÊÕ¼°¤È±¦ÊÕ¼°¤ò¼õ¤±¼è¤Ã¤Æ¡¢Ì¤Ãοô¤ò´Þ¤àÊդȴޤޤʤ¤ÊդȤËʬ¤±¤Æ¤·¤Þ¤¦¤È¤³¤í¡£!hasLeftX == !right.hasX()¤ÏÇÓ¾ŪÏÀÍýÎØ¤ÎÈÝÄê¤Ç¡¢Î¾ÊդȤâ¤Ë̤Ãοô¤ò´Þ¤ó¤Ç¤¤¤¿¤ê¡¢µÕ¤ËξÊդȤâ¤Ë̤Ãοô¤ò´Þ¤Þ¤Ê¤«¤Ã¤¿¾ì¹ç¤ËÎã³°¤òÅꤲ¤ë¡£Ì¤Ãοô¤ò´Þ¤Þ¤Ê¤¤Êý¤ÎÊդϡ¢operate()¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤·¤Æ·×»»¤·¤Æ¤·¤Þ¤¦¡£
switchʸ°Ê²¼¤Ï¡¢Ì¤Ãοô¤ò´Þ¤àÊÕ¤Îtype¥Õ¥£¡¼¥ë¥É¤ò¸«¤ÆÆ°ºî¤òÊѤ¨¤ë¡£UnaryOperation¥ª¥Ö¥¸¥§¥¯¥È¤äBinaryOperation¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¢¤ì¤Ð¡¢Äê¿ôÊÕ¤ËÂǾñ黻¤ò¤·¤Ä¤ÄºÆµ¢Åª¤Ësolve()¤ò¸Æ¤Ó½Ð¤·¡¢ºÇ¸å¤ËUnknown¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤¿¤É¤êÃ夤¤¿¤é¡¢Äê¿ôÊÕ¤òÊýÄø¼°¤Î²ò¤È¤·¤ÆÊÖ¤¹»ÅÁȤߡ£
case 'Atomic':
return constant;
type¤¬'Atomic'¤Î¾ì¹ç¡¢¤½¤ÎÊÕ¤Ï̤Ãοô¤¬Ã±ÆÈ¤Ç¸ºß¤¹¤ë¤À¤±¤ÎÊդʤΤǡ¢Äê¿ôÊÕ¤ò̤Ãοô¤Î²ò¤È¤·¤ÆÊÖ¤¹¡£
case 'Unary':
return solve(variable.operand, new UnaryOperation(variable.operator, constant));
type¤¬'Unary'¤Ç¤¢¤ì¤Ð¡¢Äê¿ôÊÕ¤ËÆ±¤¸±é»»¤ò¹Ô¤Ã¤¿¸å¡¢¥ª¥Ú¥é¥ó¥É¤ÈÄê¿ôÊÕ¤òºÆµ¢Åª¤Ësolve()´Ø¿ô¤ËÅϤ¹¡£
case 'Binary':
var canceler = ({'+': '-', '-': '+', '*': '/', '/': '*'})[variable.operator];
switch (canceler) {
case '+': case '*':
return solve(variable.operand1, new BinaryOperation(canceler, variable.operand2, constant));
case '-': case '/':
return solve(variable.operand1, new BinaryOperation(canceler, constant, variable.operand2));
}
type¤¬'Binary'¤Ç¤¢¤ì¤Ð¡¢ÂǾñ黻¤ò¤µ¤ì¤¿Äê¿ôÊդȥª¥Ú¥é¥ó¥É¤È¤òºÆµ¢Åª¤Ësolve()´Ø¿ô¤ËÅϤ¹¡£ÂǾñ黻»Ò¤¬¡¢+, *¤Î¾ì¹ç¤È-, /¤Î¾ì¹ç¤È¤Çʬ¤±¤Æ¤¤¤ë¤Î¤Ï¡¢ÂǾñ黻»Ò¤¬¸ò´¹Ë¡Â§¤òËþ¤¿¤¹¤È¤¤Ë¡¢constant¤Èvariable.operand2¤È¤òÆþ¤ìÂØ¤¨¤ë¤¿¤á¡£¤³¤Î»ÅÁȤߤò¼ÂÁõ¤·¤Ê¤¤¤È¡¢variable.operand2¤¬Ì¤Ãοô¤ò´Þ¤à¤È¤¤Ë¡¢ºÆµ¢¤¬»ß¤Þ¤é¤Ê¤¯¤Ê¤ë(variable.operand1¤¬Ì¤Ãοô¤ò´Þ¤à¤³¤È¤ò°ÅÌۤ˲¾Äꤷ¤Æ¤¤¤ë¥¢¥ë¥´¥ê¥º¥à¤Ç¤¢¤ë¤¿¤á)¡£
¥½¡¼¥¹¥³¡¼¥É
¤Þ¤À¤Þ¤ÀºÇŬ²½¤Î;ÃϤϤ¢¤ê¤½¤¦¡Ä
function extend(d, s) { for (var p in s) d[p] = s[p]; }
function calc(source) {
var sides = source.split('=');
return solve(parse(sides[0]), parse(sides[1]));
}
/** ¿ô¼°¥Ñ¡¼¥µ */
var parse = function(source) {
var unary = {'+': 1, '-': 1}, binary = {'+': 1, '-': 1, '*': 2, '/': 2};
var tokens = source.match(/x|\d+(?:\.\d+)?(?:e\d+)?|[-+*/()]/ig);
return (function parseGroup(index, end) {
var stack = [];
while (index < end) {
var operand = (function parseUnary(token) {
if (unary[token]) {
return new UnaryOperation(token, parseUnary(tokens[index++]));
} else if (token == '(') {
var depth = 0, start = index;
while (token = tokens[index++]) {
if (token == '(') depth++;
else if ((token == ')') && !depth--)
return parseGroup(start, index - 1);
}
} else {
return isNaN(token) ? new Unknown(token) : new Fraction(token);
}
})(tokens[index++]);
var operator = tokens[index++], precedence = binary[operator] || 0;
while (stack.length && precedence <= binary[stack[0]])
operand = new BinaryOperation(stack.shift(), stack.shift(), operand);
stack.unshift(operator, operand);
}
return stack.pop();
})(0, tokens.length);
};
/** °ì¸µ°ì¼¡ÊýÄø¼°¤ò²ò¤¯ */
var solve = function(left, right) {
var hasLeftX = left.hasX();
if (!hasLeftX == !right.hasX()) throw 'Error'; //XXX
var variable = hasLeftX ? left : right;
var constant = (hasLeftX ? right : left).operate();
switch (variable.type) {
case 'Atomic':
return constant;
case 'Unary':
return solve(variable.operand, new UnaryOperation(variable.operator, constant));
case 'Binary':
var canceler = ({'+': '-', '-': '+', '*': '/', '/': '*'})[variable.operator];
switch (canceler) {
case '+': case '*':
return solve(variable.operand1, new BinaryOperation(canceler, variable.operand2, constant));
case '-': case '/':
return solve(variable.operand1, new BinaryOperation(canceler, constant, variable.operand2));
}
}
};
/** ʬ¿ô¥¯¥é¥¹ */
var Fraction = function(num, den) {
var isFraction = num instanceof arguments.callee;
this.num = Number(isFraction ? num.num : num || 0);
this.den = Number(isFraction ? num.den : den || 1);
this.reduce();
};
extend(Fraction.prototype, {
valueOf: function() { return this.num / this.den; },
toString: function() { return this.num + ' / ' + this.den; },
/** Ìóʬ */
reduce: function() {
var num = Math.abs(this.num), den = Math.abs(this.den);
if (!isFinite(num) || !isFinite(den) || den === 0) throw 'Error'; //XXX
if (num) {
var sign = this.num / num * this.den / den;
while ((num % 1) || (den % 1)) { num *= 10; den *= 10; } //À°¿ô²½
var r, m = Math.max(num, den), n = Math.min(num, den); //¸ß½üË¡
while (r = m % n) { m = n; n = r; }
this.num = sign * num / n;
this.den = den / n;
} else {
this.num = 0;
this.den = 1;
}
return this;
},
/** ²Ã»» */
add: function(n) {
n = new Fraction(n);
this.num = this.num * n.den + n.num * this.den;
this.den *= n.den;
return this.reduce();
},
/** ¸º»» */
subtract: function(n) {
n = new Fraction(n);
this.num = this.num * n.den - n.num * this.den;
this.den *= n.den;
return this.reduce();
},
/** ¾è»» */
multiply: function(n) {
n = new Fraction(n);
this.num *= n.num;
this.den *= n.den;
return this.reduce();
},
/** ½ü»» */
divide: function(n) {
n = new Fraction(n);
this.num *= n.den;
this.den *= n.num;
return this.reduce();
}
});
/** ñ¹à±é»»¥¯¥é¥¹ */
var UnaryOperation = function(operator, operand) {
this.operator = operator;
this.operand = operand;
};
extend(UnaryOperation.prototype, {
type: 'Unary',
hasX: function() { return this.operand.hasX(); },
operate: function() {
switch (this.operator) {
case '-':
return this.operand.operate()['*'](-1);
case '+':
default:
return this.operand.operate();
}
}
});
/** Æó¹à±é»»¥¯¥é¥¹ */
var BinaryOperation = function(operator, operand1, operand2) {
this.operator = operator;
this.operand1 = operand1;
this.operand2 = operand2;
};
extend(BinaryOperation.prototype, {
type: 'Binary',
hasX: function() { return this.operand1.hasX() || this.operand2.hasX(); },
operate: function() { return this.operand1.operate()[this.operator](this.operand2.operate()); }
});
/** ̤Ãοô¥¯¥é¥¹ */
var Unknown = function(name) { this.name = name; };
extend(Unknown.prototype, {
type: 'Atomic',
hasX: function() { return true; },
operate: function() { throw 'This is an Unknown Value.'; }
});
/** ʬ¿ô¥¯¥é¥¹¤ò³ÈÄ¥ */
extend(Fraction.prototype, {
'+': Fraction.prototype.add,
'-': Fraction.prototype.subtract,
'*': Fraction.prototype.multiply,
'/': Fraction.prototype.divide,
type: 'Atomic',
hasX: function() { return false; },
operate: function() { return this; }
});
¥È¥é¥Ã¥¯¥Ð¥Ã¥¯URL
- http://liosk.blog103.fc2.com/tb.php/92-746c4092
1 ·ï¤Î¥È¥é¥Ã¥¯¥Ð¥Ã¥¯
- °ì¼¡ÊýÄø¼°¤ò²ò¤±¤ëÅÅÂ¥¤¥È
-
[JavaScript] ÃæÃֵˡ¤Î°ì¸µ°ì¼¡ÊýÄø¼°¤ò²ò¤¯ÅÅÂî
http://liosk.blog103.fc2.com/blog-entry-92.html
Ãæ³Ø1ǯ¤¢¤¿¤ê¤Î³§¤µ¤ó¡¢¤³¤ì¤ÏÌòΩ¤Ä¤È»×¤¤¤Þ¤¹¤è¡£
¤Þ¤¢¡¢ÊýÄø¼°¤¬²ò¤±¤ëÅÅÂî¤È¤¤¤Ã¤¿¤é¡¢
ÀìÌçŹ¤Ê¤É¤ÇÇ㤨¤ë¤Î¤Ç¤¹¤¬¡¢
º£²ó¾Ò²ð¤¹¤ë¤Î¤Ï¡¢¡Ö̵ÎÁ¡×¤...
- 2009-09-23
- ȯ¿®¸µ: ¿ʬËèÆü¹¹¿·¡ªSUGAZINE¡ª(¥·¥å¥¬¥¸¥ó)

