如何在mathjax中将矩阵与负号对齐?

时间:2018-03-18 01:55:51

标签: mathjax

如果你只是使用这样的东西:

\(
    \left[
        \begin{matrix}
            0 &  1 & 5 & 2 \\
            1 & -7 & 1 & 0 \\
            0 &  0 & 1 & 3
        \end{matrix}
    \right]
\)

负面信号不排成一行。

enter image description here

所以我一直在做的是加入\phantom{-}以抵消差异:

\(
    \left[
        \begin{matrix}
            0 &  \phantom{-}1 & 5 & 2 \\
            1 &            -7 & 1 & 0 \\
            0 &  \phantom{-}0 & 1 & 3
        \end{matrix}
    \right]
\)

enter image description here

适用于那一列,但现在列之间的宽度是不同的,除非第一列之后的每一列都至少有一个带负号的数字。所以我通过给他们一个\phantom{-}

来解决这个问题
\(
    \left[
        \begin{matrix}
            0 &  \phantom{-}1 & \phantom{-}5 & \phantom{-}2 \\
            1 &            -7 & \phantom{-}1 & \phantom{-}0 \\
            0 &  \phantom{-}0 & \phantom{-}1 & \phantom{-}3
        \end{matrix}
    \right]
\)

enter image description here

这对我来说是正确的,但我这样做的方式非常繁琐。有没有更好的方法呢?

也许我应该编写自己的脚本来自动执行所有这些操作。这对我来说似乎很理想:

<matrix>
    0  1 5 2;
    1 -7 1 0;
    0  0 1 3
</matrix>

2 个答案:

答案 0 :(得分:1)

这可能更符合您的要求:

<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS_HTML"></script>

\(
\left[
    \begin{matrix}
        0 & \hfil     1 & 5 & 2 \\
        1 & \ \llap{-}7 & 1 & 0 \\
        0 & \hfil     0 & 1 & 3
    \end{matrix}
\right]
\)

答案 1 :(得分:0)

我确信我可能是一个完全傻瓜,因为有一种更简单的方法可以做到这一点,但由于我找不到如何以正确的方式做到这一点,我自动完成了这样做。

我的代码是一个小的node.js脚本,用于转换它:

<matrix>
      1                     2   3;
    -42                    -5  -666;
      7    \color{#a38f8c}{-8}  9
</matrix>
<br>
<br>
<matrix>
    6  0  0 1;
    0 -1  0 0;
    0  0  0 0
</matrix>
<br>
<br>
<matrix>
    6 0           -9  1;
    0 1 \frac{1}{200} 0;
    0 0            0  0
</matrix>

进入这个:

\(\left[ \begin{matrix} \phantom{-}1\phantom{0} &amp; \phantom{-}2 &amp; \phantom{-}3\phantom{00} \\ -42 &amp; -5 &amp; -666 \\ \phantom{-}7\phantom{0} &amp; \color{#a38f8c}{-8} &amp; \phantom{-}9\phantom{00} \end{matrix} \right] \)
<br>
<br> 
\( \left[ \begin{matrix} 6 &amp; \phantom{-}0 &amp; \phantom{-}0 &amp; \phantom{-}1 \\ 0 &amp; -1 &amp; \phantom{-}0 &amp; \phantom{-}0 \\ 0 &amp; \phantom{-}0 &amp; \phantom{-}0 &amp; \phantom{-}0 \end{matrix} \right] \)
<br>
<br> 
\( \left[ \begin{matrix} 6 &amp; \phantom{-}0 &amp; -9 &amp; \phantom{-}1 \\ 0 &amp; \phantom{-}1 &amp; \phantom{-}\frac{1}{200} &amp; \phantom{-}0 \\ 0 &amp; \phantom{-}0 &amp; \phantom{-}0 &amp; \phantom{-}0 \end{matrix} \right] \)

看起来像这样:

enter image description here

嗯,或多或少。它需要每个<matrix>的innerHTML。这绝对不是理想的,但我没有看到有人来回答这一天。它对我有用:

let processMatrix = text => {
    // parse a matrix template string into [['a','b'],['c','d']] format
    let partitionText = text => {
        let rows = text.split(";");
        return rows.map(row => {
            row = row.trim().replace( /\s\s+/g, ' ' );
            return row.split(" ");
        });
    };

    // iterate, column first, through the matrix
    let iterateMatrix = (matrix, callback) => {
        let numRows = matrix.length;
        let numCols = matrix[0].length;

        for(let c = 0; c < numCols; c++) {
            for(let r = 0; r < numRows; r++) {
                let value = matrix[r][c];
                callback(value, r, c);
            }
        }
    }

    // does the text have \color{#a38f8c}{12345}?
    let isColored = text => /color/.test(text);

    // getter and setter for the actual value. e.g. 1 or \color{#ffffff}{1} 
    let valueRegex = /{-*\d+}/;
    let getValue = text => {
        if(isColored(text)) {
            return valueRegex.exec(text)[0].replace("{", "").replace("}", "");
        }
        else {
            return text;        
        }
    }
    let setValue = (text, newValue) => {
        if(isColored(text)) {
            return newValue; //text.replace(valueRegex, newValue)
        }
        else {
            return newValue;
        }
    }

    // how many digits does this number take? e.g. 456 takes 3 digits
    let getDigitCount = text => {
        let isFraction = /frac{/.test(text);
        if(isFraction) {
            /*let fractionParts = text.match(/{\d*}/g);
            let numeratorLength = fractionParts[0].length - 2;
            let denominatorLength = fractionParts[1].length - 2*/

            return 1; // 1 seems to look about right
        }
        else {;
            return text.match(/\d/g).length;
        }
    };

    // create a string of n zeroes
    let getDigitString = length => {
        let digitString = "";
        for(let i = 0 ; i < length;  i++) {
            digitString += "0";
        }
        return digitString;
    };

    // toString for the 2d array that is used to represent the matrix
    let matrixToString = matix => {
        matrix = matrix.map(row => {
            return row.join(" & ");
        });
        return matrix.join(" \\\\ \n");
    };

    // ACTUALLY START WORKING...
    // Step1: turn the input string into a 2d array
    let matrix = partitionText(text);

    // Step2: find and store the digit that is longest in length in each column
    let digitCounts = [];
    iterateMatrix(matrix, (value, r, c) => {
        value = getValue(value);

        let digitCount = getDigitCount(value);
        if(digitCounts.length === c) {
            digitCounts.push(0);
        }
        digitCounts[c] = digitCount > digitCounts[c] ? digitCount : digitCounts[c];
    });

    // Step3: normalize differences in length on a per column basis. e.g. [1;123;1234] => [1\phantom{000};123\phantom{0};1234]
    iterateMatrix(matrix, (value, r, c) => {
        let maxDigitsInColumn = digitCounts[c];
        let digitDifference = maxDigitsInColumn - getValue(value).length;
        if(digitDifference > 0) {
            let valueWithNormalizedLength = value + "\\phantom{" + getDigitString(digitDifference) + "}";
            matrix[r][c] = valueWithNormalizedLength;
        }
    });

    // Step4: all numbers get a negative sign, even if it's just \phantom{-} so that spacing is consistent.
    // the first column only gets a negative sign if other elements in that column have a negative sign
    let anyNegatives = false;
    iterateMatrix(matrix, (value, r, c) => {
        let isNegative = getValue(value).startsWith('-');
        anyNegatives = isNegative ? true : anyNegatives;
    });
    if(anyNegatives) {
        iterateMatrix(matrix, (value, r, c) => {
            let isFirstColumn = c === 0;
            let addNegativeToFirstColumn = false;
            if(isFirstColumn) {
                let anyNegatives = matrix.filter(r => r[0].startsWith("-")).length > 0;
                addNegativeToFirstColumn = anyNegatives;
            }
            if(isFirstColumn && addNegativeToFirstColumn === false) {
                return;
            }

            let startsWithNegative = getValue(value).startsWith("-");
            if(startsWithNegative === false) {
                matrix[r][c] = setValue(value, "\\phantom{-}" + value);
            }
        });
    }

    // STEP5: call toString and wrap it in the required syntax for a latex matrix
    let matrixWrapper = "\
        \\( \n\
            \\left[ \n\
                \\begin{matrix} \n\
                [MATRIX_LATEX] \n\
                \\end{matrix} \n\
            \\right] \n\
        \\)";

    return matrixWrapper.replace("[MATRIX_LATEX]", matrixToString(matrix));
}