# Matrix with evenly spaced columns

Similar question: How can I make a similar matrix with even column spacing?

The following code is simple to write/read/maintain, but looks terrible.

\documentclass{article}
\usepackage{amsmath}
\usepackage{mathtools}

\begin{document}

\begin{equation*}
\begin{bmatrix*}[r]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{bmatrix*}
\end{equation*}

\end{document}


This is because the negative sign adds extra space between the first and second columns, but not between the second and third.

One could naively put a \phantom{-} in each column, but this isn't right either.

\begin{equation*}
\begin{bmatrix*}[r]
\phantom{-}1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & \phantom{-}1
\end{bmatrix*}
\end{equation*}


This is because we don't need extra space to the left of each column, but an even amount of space between each column.

\begin{gather*}
\begin{bmatrix*}[r]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{bmatrix*} \\
\begin{bmatrix*}[r]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & \phantom{-}1
\end{bmatrix*}
\end{gather*}


Much better. (The second one, compared to the original above it.)

However, in larger matrices, this can easily become hard to read and quite a hassle to maintain. Is there some simple way to tell it to put an equal amount of space (say, between the right hand sides) of columns 1&2, 2&3, 3&4, ... ?

Ideally, I'd like the body of my matrices to contain nothing other than the content:

1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1


Here's a version that uses a new environment brmatrix. For the first column the standard r column is used, for the other columns we use a new column type M which also aligns the content right, but uses a fixed width \@brcolwidth. As this is a problem if the content may be wider than the cell and overlap with the other columns, an optional parameter for setting the cell width directly has been added.

A full example with the standard bmatrix in the first and the new brmatrix in the other cases:

\documentclass{article}

\usepackage{array}
\usepackage{amsmath}
\usepackage{mathtools}

\newcolumntype{M}[1]{>{\hbox to #1\bgroup\hss$}l<{$\egroup}}

\makeatletter
\newcommand\@brcolwidth{0.67em}
\newenvironment{brmatrix}{%
\left[%
\hskip-\arraycolsep
\new@ifnextchar[\@brarray{\@brarray[\@brcolwidth]}%
}{%
\endarray
\hskip -\arraycolsep
\right]%
}
\def\@brarray[#1]{\array{r*\c@MaxMatrixCols {M{#1}}}}
\makeatother

\begin{document}

\begin{equation*}
\begin{bmatrix*}[r]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{bmatrix*}
\end{equation*}

\begin{equation*}
\begin{brmatrix}
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{brmatrix}
\end{equation*}

\begin{equation*}
\begin{brmatrix}
-1 &  0 &  0 \\
0 & -1 &  0 \\
0 &  0 & -1
\end{brmatrix}
\end{equation*}

\begin{equation*}
\begin{brmatrix}[2em]
123 &   0 & 0 \\
0 & -12 & 0 \\
0 &   0 & 12345
\end{brmatrix}
\end{equation*}

\end{document}


Output:

• Thanks. I was hoping there was already something like this out there in a standard package. Ideally \@brcolwidth would be automatically determined by scanning the contents of the matrix. – Travis Bemrose Oct 26 '16 at 13:00
• @TravisBemrose: That's exactly what I show in my example - an automated way of calculating the widest elements in columns 2+. – Werner Oct 27 '16 at 17:27
• @siracusa: Is there a way to rewrite the code to include an optional vertical line (as in an augmented matrix) so that the cell widths can till be altered but a vertical line can be inserted directly between two columns? – Mark Twain Dec 27 '17 at 21:52
• @MarkTwain: The line \def\@brarray... defines the column format for the array, i.e. one r column and many M columns. You could rewrite it with a | added where you want the vertical line, I guess. But then you get the line at the same position for all matrices. – siracusa Dec 28 '17 at 15:26

The basic approach is the same as before, namely using \makebox, except that I automated as much as possible.

The main drawback with mymatrix is that you have to specify the number of columns. Note, the minimum spacing is still 2\arraycolsep.

\documentclass{article}
\usepackage{amsmath}
\usepackage{mathtools}
\usepackage{array}
\usepackage{collcell}

\newlength{\mycolwidth}
\settowidth{\mycolwidth}{$-1$}

\newcommand{\mybox}[1]{\makebox[\mycolwidth][r]{$#1$}}

\newcolumntype{R}{>{\collectcell\mybox}r<{\endcollectcell}}

\newenvironment{mymatrix}[1]% #1 = total number of columns
{\count1=#1\relax
\left[\array{@{}r*{\number\count1}R@{}}}%
{\endarray\right]}

\begin{document}

\begin{equation*}
\begin{bmatrix*}[r]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{bmatrix*}
\begin{mymatrix}{3}
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{mymatrix}
\end{equation*}

\end{document}

• I was going to delete this after @siracusa solution (so \c@MaxMatrixCols gives the number of columns), but decided that the stylistic contrasts might prove informative. – John Kormylo Oct 26 '16 at 4:41

Here is an automated version called BMatrix that takes an optional argument for alignment, adjusting all but the first column of the BMatrix environment to have a width equal to the maximum of the entries.

\documentclass{article}

\usepackage{mathtools,collcell,eqparbox}

\newcounter{BMatrix}

\newlength{\maxwd}
\newcommand{\setmaxwd}[1]{%
\eqmakebox[BM-\theBMatrix][\BMalign]{$#1$}%
}

\MHInternalSyntaxOn
\newenvironment{BMatrix}[1][c]{
\def\BMalign{#1}
\stepcounter{BMatrix}
\left[\hskip -\arraycolsep
\MH_let:NwN \@ifnextchar \MH_nospace_ifnextchar:Nnn
\array{ #1 *{\numexpr\c@MaxMatrixCols-1} {>{\collectcell\setmaxwd}#1<{\endcollectcell}}}
}{
\endarray \hskip -\arraycolsep
\right]
}
\MHInternalSyntaxOff
\makeatother

\begin{document}

\begin{gather*}
\texttt{bmatrix*[c]} \\
\begin{bmatrix*}[c]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{bmatrix*}
\begin{bmatrix*}[c]
123 &   0 &     0 \\
0 & -12 &     0 \\
0 &   0 & 12345
\end{bmatrix*} \\
\texttt{BMatrix[c]} \\
\begin{BMatrix}[c]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{BMatrix}
\begin{BMatrix}[c]
123 &   0 &     0 \\
0 & -12 &     0 \\
0 &   0 & 12345
\end{BMatrix} \\
\texttt{bmatrix*[r]} \\
\begin{bmatrix*}[r]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{bmatrix*}
\begin{bmatrix*}[r]
123 &   0 &     0 \\
0 & -12 &     0 \\
0 &   0 & 12345
\end{bmatrix*} \\
\texttt{BMatrix[r]} \\
\begin{BMatrix}[r]
1 &  0 & 0 \\
0 & -1 & 0 \\
0 &  0 & 1
\end{BMatrix}
\begin{BMatrix}[r]
123 &   0 &     0 \\
0 & -12 &     0 \\
0 &   0 & 12345
\end{BMatrix}
\end{gather*}

\end{document}


Each entry in columns 2 and higher are set inside an \eqmakebox with a per-BMatrix unique tag. The eqparbox package then ensures the width of these entries are the same, together with an appropriate alignment specifier. Width calculations uses the .aux file and there may require multiple compilations (at first). The first column is left untouched.

Try this:

\documentclass{article}
\usepackage{amsmath}
\usepackage{mathtools}
\begin{document}
\newcommand{\widest}{\ensuremath{-1}}
\newcommand{\newWidth}[1]{\makebox[\widthof{\widest}]{\ensuremath{#1}}}

\begin{equation*}
\left[\begin{array}{rrr}
1 &  0 & 0 \\
0 &\newWidth{-1}& 0 \\
0 &  0 & -1
\end{array}\right]
\end{equation*}

\end{document}


Output:

• It seems to me that all this is doing is putting a box around the (2,2) entry where you've put \newWidth. When I put 0 & 0 & 1 in the bottom row, the right column no longer has the intended spacing. – Travis Bemrose Oct 26 '16 at 13:05