簡體   English   中英

擴展代數項

[英]Expansion of algebraic term

我試圖擴展代數術語。

(x+1)(x+1)/x => x + 2 + x^-1
(x+1)^3 => x^3 + 3x^2 + 3x + 1
(x^2*x)(x^2) => x^5

這是我的嘗試。 我嘗試了很多方法來解決下面的問題。

問題:

  • 喜歡的術語應該加在一起

  • (x+1)(x+1)(x+1)應該有效。

  • (x+1)^2應等於(x+1)(x+1)

  • x(x+1)應該有效

  • 1x^n應該只是x^n

  • 應該沒有0x^n項。

  • nx^0項應該只是n

代碼片段:

 function split(input) { return ((((input.split(")(")).toString()).replace(/\\)/g, "")).replace(/\\(/g, "")).split(','); } function strVali(str) { str = str.replace(/\\s+/g, ""); var parts = str.match(/[+\\-]?[^+\\-]+/g); // accumulate the results return parts.reduce(function(res, part) { var coef = parseFloat(part) || +(part[0] + "1") || 1; var x = part.indexOf('x'); var power = x === -1 ? 0: part[x + 1] === "^" ? +part.slice(x + 2) : 1; res[power] = (res[power] || 0) + coef; return res; }, {}); } function getCoeff(coeff) { var powers = Object.keys(strVali(coeff)); var max = Math.max.apply(null, powers); var result = []; for(var i = max; i >= 0; i--) result.push(strVali(coeff)[i] || 0); return result; } function evaluate(expression) { var term1 = getCoeff(expression[0]); var term2 = getCoeff(expression[1]); var expand = ""; for ( var j = 0; j < term1.length; j++ ) { for ( var i = 0; i < term2.length; i++ ) { expand += Number(term1[j] * term2[i]) + 'x^ ' + (Number(term1.length) - 1 - j + Number(term2.length) - 1 - i) + ' + '; }} var final = ""; for ( var Z = 0; Z < getCoeff(expand).length; Z++) { final += ' ' + getCoeff(expand)[Z] + 'x^ {' + (getCoeff(expand).length - Z - 1) + '} +'; } final = "$$" + ((((((final.replace(/\\+[^\\d]0x\\^ \\{[\\d]+\\}/g,'')).replace(/x\\^ \\{0}/g,'')).replace(/x\\^ \\{1}/g,'x')).replace(/[^\\d]1x\\^ /g,'+ x^')).replace(/\\+ -/g,' - ')).slice(0, -1)).substring(1,(final.length)) + "$$"; document.getElementById('result').innerHTML = final; MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]); } function caller() { var input = document.getElementById('input').value; evaluate(split(input)); } 
 div.wrapper { width: 100%; height:100%; border:0px solid black; } input[type="text"] { display: block; margin : 0 auto; padding: 10px; font-size:20px; } button{ margin:auto; display:block; background-color: white; color: black; border: 2px solid #555555; padding-left: 20px; padding-right: 20px; font-size: 20px; margin-top:10px; } button:hover { box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19); } 
 <script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML"> </script> <div class='wrapper'><input id="input" title="Enter Expression" type="text" value="(x^2+x+1)(x^2+x+1)"></div> <div> <button onclick="caller()">Click</button></div> <div id="result">$$x^4 + 2x^3 + 3x^2 + 2x + 1$$</div> 

參考:

  1. 如何計算javascript中多項式展開的系數

  2. 獲得代數項的系數

  3. 如何在角色前獲得一個詞?

編輯:當問題沒有包括-/運算符時,我重寫了我的原始答案 我的新答案支持-/

由於你沒有定義一個精確的語法,我做了一些假設。 我支持+-/^運算符和隱式乘法。 這些可以對數字, x(...)表達式進行操作,除了^運算符的右側必須是數字。 我允許令牌之間的空格。

限制: -是二元而非一元-運算符,所以x-2如果正常, -2本身就是語法錯誤。 /是有限的。 您可以將值除以具有單個系數的值,例如2 ,'x', 2x^2 ,但不能除以不能具有1/(x^2+1) ,這將評估為無限級數。

它首先接受字符串並將其包裝在'tokenizer'中,它允許您一次查看一個令牌,其中令牌是數字, x( )或運算符。

然后調用evaluateSum()來計算由+-分隔的事物,其中每個事物都是由evaluateProduct()的產品。 這反過來使用evaluatePower()evaluatePower() ^ 最后, evaluateTerm()查找x ,數字和括號內的子表達式,這些子表達式使用evaluateSum()遞歸evaluateSum() 此層次結構創建正確的運算符優先級和評估順序。

評估的每一層都返回一個類似於數組的“系數”對象,但可能包含巨型索引。 例如, [1,0,1]表示1+x^2

它可以處理任意數量的嵌套括號和許多其他情況,如xx(x)x^3 2^38 我為語法錯誤添加了一些拋出,例如2^x是非法的。

function makeTokenizer(source) {
    var c, i, tokenizer;
    i = 0; // The index of the current character.
    c = source.charAt(i); // The current character.
    function consumeChar() { // Move to next c, return previous c.
        var prevC = c;
        i += 1;
        c = source.charAt(i);
        return prevC;
    }
    tokenizer = {
        next : function () {
            var str;
            while (c === ' ') { // Skip spaces
                consumeChar();
            }
            if (!c) {
                tokenizer.token = undefined; // End of source
            } else if (c >= '0' && c <= '9') { // number
                str = consumeChar(); // First digit
                while (c >= '0' && c <= '9') { // Look for more digits.
                    str += consumeChar();
                }
                tokenizer.token = Number(str);
            } else if (c === "x") {
                tokenizer.token = consumeChar();
            } else { // single-character operator
                tokenizer.token = consumeChar();
            }
        }
    };
    tokenizer.next(); // Load first token.
    return tokenizer;
}
function makeCoefficients() { // Make like an array but can have -ve indexes
    var min = 0, max = 0, c = {};
    return {
        get: function (i) {
            return c[i] || 0;
        },
        set: function (i, value) {
            c[i] = value;
            min = Math.min(i, min);
            max = Math.max(i + 1, max);
            return this; // for chaining
        },
        forEach: function (callback) {
            var i;
            for (i = min; i < max; i += 1) {
                if (this.get(i)) {
                    callback(this.get(i), i);
                }
            }
        },
        toString: function () {
            var result = "", first = true;
            this.forEach(function (val, power) {
                result += (val < 0 || first) ? "" : "+";
                first = false;
                result += (val === 1 && power !== 0) ? "" : val;
                if (power) {
                    result += "x";
                    if (power !== 1) {
                        result += "^" + power;
                    }
                }
            });
            return result;
        },
        toPowerOf: function (power) {
            if (power === 0) {
                return makeCoefficients().set(0, 1); // Anything ^0 = 1
            }
            if (power === 1) {
                return this;
            }
            if (power < 0) {
                throw "cannot raise to negative powers";
            }
            return this.multiply(this.toPowerOf(power - 1));
        },
        multiply: function (coefficients) {
            var result = makeCoefficients();
            this.forEach(function (a, i) {
                coefficients.forEach(function (b, j) {
                    result.set(i + j, result.get(i + j) + a * b);
                });
            });
            return result;
        },
        divide: function (coefficients) {
            // Division is hard, for example we cannot do infinite series like:
            // 1/(1 + x^2) = sum_(n=0 to infinity) 1/2 x^n ((-i)^n + i^n)
            // So we do a few easy cases only.
            var that = this, result = makeCoefficients(), done;
            coefficients.forEach(function (value, pow) {
                that.forEach(function (value2, pow2) {
                    result.set(pow2 - pow, value2 / value);
                });
                if (done) {
                    throw "cannot divide by " + coefficients.toString();
                }
                done = true;
            });
            return result;
        },
        add: function (coefficients, op) {
            var result = makeCoefficients();
            this.forEach(function (value, i) {
                result.set(value, i);
            });
            op = (op === "-" ? -1 : 1);
            coefficients.forEach(function (value, i) {
                result.set(i, result.get(i) + value * op);
            });
            return result;
        }
    };
}
var evaluateSum; // Called recursively
function evaluateTerm(tokenizer) {
    var result;
    if (tokenizer.token === "(") {
        tokenizer.next();
        result = evaluateSum(tokenizer);
        if (tokenizer.token !== ")") {
            throw ") missing";
        }
        tokenizer.next();
    } else if (typeof tokenizer.token === "number") {
        result = makeCoefficients().set(0, tokenizer.token);
        tokenizer.next();
    } else if (tokenizer.token === "x") {
        tokenizer.next();
        result = makeCoefficients().set(1, 1); // x^1
    } else {
        return false; // Not a 'term'
    }
    return result;
}
function evaluatePower(tokenizer) {
    var result;
    result = evaluateTerm(tokenizer);
    if (tokenizer.token === "^") {
        tokenizer.next();
        if (typeof tokenizer.token !== "number") {
            throw "number expected after ^";
        }
        result = result.toPowerOf(tokenizer.token);
        tokenizer.next();
    }
    return result;
}
function evaluateProduct(tokenizer) {
    var result, term, divOp;
    result = evaluatePower(tokenizer);
    if (!result) {
        throw "Term not found";
    }
    while (true) {
        divOp = (tokenizer.token === "/");
        if (divOp) {
            tokenizer.next();
            term = evaluatePower(tokenizer);
            result = result.divide(term);
        } else {
            term = evaluatePower(tokenizer);
            if (!term) {
                break;
            }
            result = result.multiply(term);
        }
    }
    return result;
}
function evaluateSum(tokenizer) {
    var result, op;
    result = evaluateProduct(tokenizer);
    while (tokenizer.token === "+" || tokenizer.token === "-") {
        op = tokenizer.token;
        tokenizer.next();
        result = result.add(evaluateProduct(tokenizer), op);
    }
    return result;
}

function evaluate(source) {
    var tokenizer = makeTokenizer(source),
        coefficients = evaluateSum(tokenizer);
    if (tokenizer.token) {
        throw "Unexpected token " + tokenizer.token;
    }
    console.log(source + " => " + coefficients.toString());
}

// Examples:
evaluate("(x+1)(x+1)"); // => 1+2x+x^2
evaluate("(x+1)^2"); // => 1+2x+x^2
evaluate("(x+1)(x+1)(x+1)"); // => 1+3x+3x^2+x^3
evaluate("(x+1)^3"); // => 1+3x+3x^2+x^3
evaluate("(x)(x+1)"); // => x+x^2
evaluate("(x+1)(x)"); // => x+x^2
evaluate("3x^0"); // => 3
evaluate("2^3"); // => 8
evaluate("(x+2x(x+2(x+1)x))"); // => x+6x^2+4x^3
evaluate("(x+1)(x-1)"); // => -1+x^2
evaluate("(x+1)(x+1)/x"); // x^-1+2+x
//evaluate("(x+1)/(x^2 + 1)"); //throws  cannot divide by 1+2x

它可以處理+-/和隱式乘法。 它會相應地擴展括號,並在刪除括號ed版本時將它們添加到原始表達式中。 它會相應地收集相同的條款。 限制:它不能除以多項式,也不支持*運算符。

 function strVali(str) { str = str.replace(/\\s+/g, ""); var parts = str.match(/[+\\-]?[^+\\-]+/g); return parts.reduce(function(res, part) { var coef = parseFloat(part) || +(part[0] + "1") || 1; var x = part.indexOf('x'); var power = x === -1 ? 0: part[x + 1] === "^" ? +part.slice(x + 2) : 1; res[power] = (res[power] || 0) + coef; return res; }, {}); } function getCoeff(coeff) { var powers = Object.keys(strVali(coeff)); var max = Math.max.apply(null, powers); var result = []; for(var i = max; i >= 0; i--) result.push(strVali(coeff)[i] || 0); return result; } function format(str) { str = ' ' + str; str = str.replace(/-/g,'+-').replace(/x(?!\\^)/g,'x^1').replace(/([+\\/*)(])(\\d+)([+\\/*)(])/g,'$1$2x^0$3').replace(/([^\\d])(x\\^-?\\d+)/g,'$11$2').replace(/(-?\\d+x\\^\\d+)(?=\\()/g,'($1)').replace(/(\\))(-?\\d+x\\^\\d+)/g,'$1($2)').replace(/([^\\)\\/])(\\()([^\\*\\/\\(\\)]+?)(\\))(?![(^\\/])/g,'$1$3'); str = str.replace(/(\\([^\\(\\)]+?\\))\\/(\\d+x\\^-?\\d+)/g,'$1/($2)').replace(/(\\d+x\\^-?\\d+)\\/(\\d+x\\^-?\\d+)/g,'($1)/($2)').replace(/(\\d+x\\^-?\\d+)\\/(\\(\\d+x\\^-?\\d+\\))/g,'($1)/$2'); return str; } function expBrackets(str) { var repeats = str.match(/\\([^\\(\\)]+?\\)\\^\\d+/g); if ( repeats === null ) { return str; } else { var totalRepeat = ''; for ( var t = 0; t < repeats.length; t++ ) { var repeat = repeats[t].match(/\\d+$/); for ( var u = 0; u < Number(repeat); u++ ) { totalRepeat += repeats[t].replace(/\\^\\d+$/,''); } str = str.replace(/\\([^\\(\\)]+?\\)\\^\\d+/, totalRepeat); totalRepeat = ''; } return str; } } function multiply(str) { var pairs = str.match(/\\([^\\(\\)]+?\\)\\([^\\(\\)]+?\\)/g); if ( pairs !== null ) { while ( pairs !== null ) { var output = ''; for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].slice(1).slice(0, -1).split(')('); var firstCoeff = getCoeff(pair[0]); var secondCoeff = getCoeff(pair[1]); for (var j = 0; j < firstCoeff.length; j++) { for (var k = 0; k < secondCoeff.length; k++) { output += firstCoeff[j] * secondCoeff[k] + 'x^' + Number(firstCoeff.length - 1 - j + secondCoeff.length - 1 - k) + '+'; } } var regexp = new RegExp(pairs[i].replace(/\\(/g,'\\\\(').replace(/\\+/g,'\\\\+').replace(/\\)/g,'\\\\)').replace(/\\^/g,'\\\\^').replace(/\\-/g,'\\\\-')); str = str.replace(regexp, '(' + (output.slice(0, -1).replace(/[^\\d]0x\\^\\d+/g,'')) + ')'); output = ''; } pairs = str.match(/\\([^\\(\\)]+?\\)\\([^\\(\\)]+?\\)/g); } } else { } str = str.replace(/\\+/g,' + '); return str; } function divide(str) { if ( str.match(/\\/(\\(-?\\d+x\\^-?\\d+.+?\\))/g) === null && str.match(/\\//g) !== null ) { while ( pairs !== null ) { var pairs = str.match(/\\([^\\(\\)]+?\\)\\/\\([^\\(\\)]+?\\)/g); var output = ''; for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].slice(1).slice(0, -1).split(')/('); var firstCoeff = getCoeff(pair[0]); var secondCoeff = getCoeff(pair[1]); for (var j = 0; j < firstCoeff.length; j++) { for (var k = 0; k < secondCoeff.length; k++) { output += firstCoeff[j] / secondCoeff[k] + 'x^' + Number(firstCoeff.length - 1 - j - secondCoeff.length + 1 + k) + '+'; output = output.replace(/([+-])Infinityx\\^\\-?\\d+/g,'').replace(/([+-])NaNx\\^\\-?\\d+/g,''); } } var regexp = new RegExp(pairs[i].replace(/\\(/g,'\\\\(').replace(/\\+/g,'\\\\+').replace(/\\)/g,'\\\\)').replace(/\\^/g,'\\\\^').replace(/\\-/g,'\\\\-')); str = str.replace(regexp, '(' + (output.slice(0, -1).replace(/[^\\d]0x\\^-?\\d+/g,'')) + ')'); output = ''; } pairs = str.match(/\\([^\\(\\)]+?\\)\\/\\([^\\(\\)]+?\\)/g); } } else { } return str; } function evaluate(str) { var result = format(divide(format(multiply(expBrackets(format((str))))))); var resultCollect = ''; result = result.replace(/\\s+/g, "").replace(/[^\\d]0x\\^-?\\d+/g,'').replace(/\\+/g,' + '); if ( result === '') { document.getElementById('result').innerHTML = '$$' + str + '$$' + '$$ = 0 $$'; MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]); } else if ( result.match(/-?\\d+x\\^-\\d+/g) === null && str.match(/\\/(\\(-?\\d+x\\^-?\\d+.+?\\))/g) === null) { for ( var i = 0; i < getCoeff(result).length; i++ ) { resultCollect += getCoeff(result)[i] + 'x^' + Number(getCoeff(result).length - 1 - i) + '+' ; } if ( resultCollect !== '') resultCollect = '$$ = ' + resultCollect.slice(0,-1).replace(/[^\\d]0x\\^-?\\d+/g,'').replace(/\\+/g,' + ').replace(/x\\^0/g,'').replace(/x\\^1(?!\\d+)/g,'x').replace(/\\^(-?\\d+)/g,'\\^\\{$1\\}').replace(/\\+ -/g,' - ') + '$$'; else resultCollect = 'Error: Trying to divide by a polynomial '; document.getElementById('result').innerHTML = '$$' + str.replace(/\\^(-?\\d+)/g,'\\^\\{$1\\}') + '$$' + resultCollect; MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]); } else { resultCollect = '$$ = ' + result.replace(/\\^(-?\\d+)/g,'\\^\\{$1\\}') + '$$'; document.getElementById('result').innerHTML = '$$' + str.replace(/\\^(-?\\d+)/g,'\\^\\{$1\\}').replace(/\\+ -/g,' - ') + '$$' + resultCollect; MathJax.Hub.Queue(["Typeset", MathJax.Hub, document.getElementById('result')]); } } function caller() { var input = document.getElementById('input').value; evaluate(input); } 
 div.wrapper { width: 100%; height:100%; border:0 solid black; } input[type="text"] { display: block; margin : 0 auto; padding: 10px; font-size:20px; } button{ margin:auto; display:block; background-color: white; color: black; border: 2px solid #555555; padding-left: 20px; padding-right: 20px; font-size: 20px; margin-top:10px; } button:hover { box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19); } 
 <script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML"> </script> <input id="input" type="text" title="Enter Expression: "> <button onclick="caller()">Click</button> <div id="result"></div> <div id="errors"></div> 

我的方法使用了兩個輔助類:

- Term :存儲系數和對象,其中的鍵是變量,其值是指數。 它具有確定術語是否“相同”的方法(即它們是否具有相同的指數相同的變量,從而允許它們被添加),添加術語和乘法項。 - Polynomial :它存儲一系列術語。 它具有添加兩個多項式,乘以兩個多項式和簡化多項式的方法(消除具有0個系數的項並組合類似項)。

它有兩個實質的輔助函數: - findOuterParens - 給定一個字符串,該函數返回左右括號的第一個最外面的一對的索引。 - parseExpressionStr - 此函數使用正則表達式將字符串拆分為三種類型的子串:1)數字,2)符號(即變量,如'x'或'y'),或3)運算符(*) , - ,+,^,/)。 它為前兩種類型創建Polynomial對象,並將運算符保留為字符串。

expand函數運行show。 它接收一個字符串並返回一個Polynomial對象,表示字符串中Polynomial的展開形式。 它的工作方式如下:1)它通過遞歸處理括號。 它使用findOuterParens來查找所有最外層的父級子串。 因此,對於“3x *(x + 4)+(2(y + 1))* t”,它將找到“x + 4”和“2(y + 1)”作為父級子串。 然后它將這些傳遞給自己進行進一步的解析。 對於“2(y + 1)”,它將“y + 1”標識為帶括號的子字符串,並將其傳遞給自身,以用於此示例的三個遞歸級別。 2)它使用parseExpressionStr處理字符串的其他部分。 在步驟1和2之后,它有一個包含多項式對象和運算符的數組(存儲為字符串)。 然后進行簡化和擴展。 3)它將減法子問題轉換為加法子問題,方法是將全部用+替換,並將所有多項式乘以-1。 4)它將除法子問題轉換為乘法子問題,方法是用*替換/,並將/后面的Polynomial反轉。 如果/后面的多項式有多個項,則會拋出錯誤。 5)它通過用一系列乘法替換^來將冪子問題轉換為乘法子問題。 6)它增加了隱含*。 也就是說,如果兩個多項式元素在數組中彼此相鄰,則推斷出它們是相乘的,例如'2 * x'=='2x'。 7)現在數組具有與'+'或'*'交替的多項式對象。 它首先執行所有多項式乘法,然后執行所有加法。 8)它執行最終的簡化步驟並返回得到的擴展多項式。

 <html> <head></head> <body></body> <script> function findOuterParens(str) { var leftIndex = str.indexOf('('), leftNum = 1, rightNum = 0; if (leftIndex === -1) return for (var i=leftIndex+1; i<str.length; i++) { if (str[i] === '(') leftNum++; else if (str[i] === ')') rightNum++, rightIndex=i; if (leftNum === rightNum) return {start: leftIndex, end: rightIndex} } throw Error('Parenthesis at position ' + leftIndex + ' of "' + str + '" is unpaired.'); } function parseExpressionStr(inputString) { var result = [], str = inputString; while (str) { var nextPart = str.match(/([\\d]+)|([\\+\\-\\^\\*\\/])|([a-zA-z])/); if (!nextPart) return result; if (nextPart.length === 0) throw Error('Unable to parse expression string "' + inputString + '". Remainder "' + str + '" could not be parsed.'); else if (nextPart[1]) // First group (digits) matched result.push(new Polynomial(parseFloat(nextPart[0]))); else if (nextPart[3]) // Third group (symbol) matched result.push(new Polynomial(nextPart[0])); else // Second group (operator) matched result.push(nextPart[0]); str = str.substring(nextPart.index+nextPart[0].length); } return result } function isOperator(char) { return char === '*' || char === '/' || char === '^' || char === '+' || char === '-'; } function Polynomial(value) { this.terms = (value!==undefined) ? [new Term(value)] : []; } Polynomial.prototype.simplify = function() { for (var i=0; i<this.terms.length-1; i++) { if (this.terms[i].coeff === 0) { this.terms.splice(i--, 1); continue; } for (var j=i+1; j<this.terms.length; j++) { if (Term.same(this.terms[i], this.terms[j])) { this.terms[i] = Term.add(this.terms[i], this.terms[j]); this.terms.splice(j--, 1); } } } } Polynomial.add = function(a, b) { var result = new Polynomial(); result.terms = a.terms.concat(b.terms); result.simplify(); return result } Polynomial.multiply = function(a, b) { var result = new Polynomial(); a.terms.forEach(function(aTerm) { b.terms.forEach(function (bTerm) { result.terms.push(Term.multiply(aTerm, bTerm)); }); }); result.simplify(); return result } Polynomial.prototype.toHtml = function() { var html = '' for (var i=0; i<this.terms.length; i++) { var term = this.terms[i]; if (i !== 0) html += (term.coeff < 0) ? ' - ' : ' + '; else html += (term.coeff < 0) ? '-' : ''; var coeff = Math.abs(term.coeff); html += (coeff === 1 && Object.keys(term.symbols).length > 0) ? '' : coeff; for (var symbol in term.symbols) { var exp = term.symbols[symbol]; exp = (exp !== 1) ? exp : ''; html += symbol + '<sup>' + exp + '</sup>'; } } return html; } function Term(value) { this.symbols = {}; if (typeof value==='string') { // Symbol this.symbols[value] = 1; this.coeff = 1; } else if (typeof value==='number') { // Number this.coeff = value; } else { this.coeff = 1; } } Term.same = function(a, b) { if (Object.keys(a.symbols).length != Object.keys(b.symbols).length) return false else for (var aSymbol in a.symbols) if (a.symbols[aSymbol] != b.symbols[aSymbol]) return false return true } Term.add = function(a, b) { var result = new Term(); Object.assign(result.symbols, a.symbols); result.coeff = a.coeff + b.coeff; return result } Term.multiply = function(a, b) { var result = new Term(); Object.assign(result.symbols, a.symbols); for (var symbol in b.symbols) { if (!(symbol in result.symbols)) result.symbols[symbol] = 0; result.symbols[symbol] += b.symbols[symbol]; if (result.symbols[symbol] === 0) delete result.symbols[symbol]; } result.coeff = a.coeff * b.coeff; return result } function expand(str) { var result = []; var parens = findOuterParens(str); while (parens) { result = result.concat(parseExpressionStr(str.slice(0,parens.start))); result.push(expand(str.slice(parens.start+1, parens.end))) str = str.slice(parens.end+1); parens = findOuterParens(str); } result = result.concat(parseExpressionStr(str)); // Move -s to coefficients var minus = result.indexOf('-'), minusPoly = new Polynomial(-1); while (minus !== -1) { result[minus] = '+'; result[minus+1] = Polynomial.multiply(minusPoly, result[minus+1]); minus = result.indexOf('-'); } // Get rid of +s that follow another operator var plus = result.indexOf('+'); while (plus !== -1) { if (plus===0 || isOperator(result[plus-1])) { result.splice(plus--, 1); } plus = result.indexOf('+', plus+1); } // Convert /s to *s var divide = result.indexOf('/'); while (divide !== -1) { result[divide] = '*'; var termsToInvert = result[divide+1].terms; if (termsToInvert.length > 1) throw Error('Attempt to divide by a polynomial with more than one term.'); var termToInvert = termsToInvert[0]; for (var symbol in termToInvert.symbols) { termToInvert.symbols[symbol] = -termToInvert.symbols[symbol]; } termToInvert.coeff = 1/termToInvert.coeff; divide = result.indexOf('/'); } // Convert ^s to *s var power = result.indexOf('^'); while (power !== -1) { var exp = result[power+1]; if (exp.terms.length > 1 || Object.keys(exp.terms[0].symbols).length != 0) throw Error('Attempt to use non-number as an exponent'); exp = exp.terms[0].coeff; var base = result[power-1]; var expanded = [power-1, 3, base]; for (var i=0; i<exp-1; i++) { expanded.push('*'); expanded.push(base); } result.splice.apply(result, expanded); power = result.indexOf('^'); } // Add implicit *s for (var i=0; i<result.length-1; i++) if (!isOperator(result[i]) && !(isOperator(result[i+1]))) result.splice(i+1, 0, '*'); // Multiply var mult = result.indexOf('*'); while (mult !== -1) { var product = Polynomial.multiply(result[mult-1], result[mult+1]); result.splice(mult-1, 3, product); mult = result.indexOf('*'); } // Add var add = result.indexOf('+'); while (add !== -1) { var sum = Polynomial.add(result[add-1], result[add+1]); result.splice(add-1, 3, sum); add = result.indexOf('+'); } result[0].simplify(); return result[0]; } var problems = ['(x+1)(x+1)/x', '(x+1)^3', '(x^2*x)(x^2)', '(x+1)(x+1)(x+1)', '(x+1)^2', 'x(x+1)', '1x^4', '(x + (x+2))(x+5)', '3x^0', '2^3', '(x+2x(x+2(x+1)x))', '(x+1)(x-1)', '(x+1)(y+1)', '(x+y+t)(q+x+7)']; var solutionHTML = ''; for (var i = 0; i<problems.length; i++) { solutionHTML += problems[i] + ' => ' + expand(problems[i]).toHtml() + '<br>'; } document.body.innerHTML = solutionHTML; </script> </html> 

它輸出:

在此輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM