使用 pgfplotstable 格式化复数数组

使用 pgfplotstable 格式化复数数组

假设我有两个 csv 文件,分别表示一个复杂矩阵的实部和虚部。我想在 LaTeX 中很好地显示这个矩阵。困难在于正确地对数字进行舍入,并且如果数字舍入为 0 则不显示它们。

例如,1.0000000e+00 和 5.0000000e-01 应该给出 1+0.5i,而 5.0000000e-01 和 0.0000000e+00 不应该显示虚部(即 0.5)。

我从这些问题开始: 使用 siunitx 将复数对齐到表格中心合并 csv 的列但无法提出令人满意的解决方案。

这里就是开始!

\documentclass{article}
\usepackage{pgfplotstable}

\begin{filecontents}{blah_real.csv}
  re1              re2
  1.0000000e+00    1.0000000e+00
  5.0000000e-01    5.0000000e-01
  0.0000000e+00    0.0000000e+00
  5.0000000e-01    5.0000000e-01
\end{filecontents}

\begin{filecontents}{blah_im.csv}
  0.0000000e+00   0.0000000e+00
  5.0000000e-01   5.0000000e-01
  1.0000000e+00   1.0000000e+00
  5.0000000e-01   5.0000000e-01
\end{filecontents}


\begin{document}

\newcommand{\complex}[1]{%
  \pgfplotstableread[col sep=space, trim cells=true]{#1_real.csv}\real
  \pgfplotstableread[col sep=space, trim cells=true, header=false]{#1_im.csv}\imaginary

  \pgfplotstablecreatecol[copy column from table={\imaginary}{[index] 0}]{im1}{\real}
  \pgfplotstablecreatecol[copy column from table={\imaginary}{[index] 1}]{im2}{\real}


  \pgfplotstabletypeset[
  columns/complex1/.style={string type, column name={}},
  create on use/complex1/.style={%
    create col/assign/.code={%
      \edef\value{%
        \noexpand
        \pgfmathprintcomplexnumber[fixed zerofill]{\thisrow{re1}}{\thisrow{im1}}}
      \pgfkeyslet{/pgfplots/table/create col/next content}\value
    }
  },
  columns/complex2/.style={string type, column name={}},
  create on use/complex2/.style={%
    create col/assign/.code={%
      \edef\value{%
        \noexpand
        \pgfmathprintcomplexnumber[fixed zerofill]{\thisrow{re2}}{\thisrow{im2}}}
      \pgfkeyslet{/pgfplots/table/create col/next content}\value
    }
  },
  columns={complex1, complex2}
  ]{\real}
}

\makeatletter

\def\pgfmathprintcomplexnumber{%
  % \protect allows to supply \pgfmathprintnumber inside of latex
  % captions. The \csname yields \relax in case protect is undefined.
  \pgf@texdist@protect\pgfmathprintcomplexnumber@protected
}%
\def\pgfmathprintcomplexnumber@protected{%
  \pgfutil@ifnextchar[%
  {\pgfmathprintcomplexnumber@OPT}%
  {\pgfmathprintcomplexnumber@noopt}%
}

\def\pgfmathprintcomplexnumber@noopt#1#2{%
  \begingroup
  \pgfmathprintnumber@{#1}%
  \let\pgfmathresultreal\pgfmathresult
  \pgfmathfloatparsenumber{\pgfmathresult}
  \pgfmathfloatifflags{\pgfmathresult}{0}{
    \let\pgfmathresultreal\empty
    \pgfqkeys{/pgf/number format}{showpos=false}%
  }{
    \pgfqkeys{/pgf/number format}{showpos=true}%
  }%
  \pgfmathprintnumber@{#2}%
  \let\pgfmathresultim\pgfmathresult
  \pgfmathfloatparsenumber{\pgfmathresult}
  \pgfmathfloatifflags{\pgfmathresult}{0}{%
    \let\pgfmathresultim\empty
  }{
    \edef\pgfmathresultim{\pgfmathresultim i}
  }%
  \ifpgfmathprintnumber@assumemathmode
  \pgfmathresultreal\pgfmathresultim
  \else
  \pgfutilensuremath{\pgfmathresultreal\pgfmathresultim}%
  \fi
  \endgroup
}%

\def\pgfmathprintcomplexnumber@OPT[#1]#2#3{%
  \begingroup
  \pgfqkeys{/pgf/number format}{#1}%
  \pgfmathprintnumber@{#2}%
  \let\pgfmathresultreal\pgfmathresult
  \pgfmathfloatparsenumber{\pgfmathresult}
  \pgfmathfloatifflags{\pgfmathresult}{0}{
    \let\pgfmathresultreal\empty
    \pgfqkeys{/pgf/number format}{showpos=false}%
  }{
    \pgfqkeys{/pgf/number format}{showpos=true}%
  }%
  \pgfmathprintnumber@{#3}%
  \let\pgfmathresultim\pgfmathresult
  \pgfmathfloatparsenumber{\pgfmathresult}

  \pgfmathfloatifflags{\pgfmathresult}{0}{%
    \let\pgfmathresultim\empty
  }{%
    \edef\pgfmathresultim{\pgfmathresultim i}
  }%
  \ifpgfmathprintnumber@assumemathmode
  \pgfmathresultreal\pgfmathresultim
  \else
  \pgfutilensuremath{\pgfmathresultreal\pgfmathresultim}%
  \fi
  \endgroup
}%

\makeatother

\complex{blah}

\end{document}

知道如何做到这一点吗?

编辑:几乎可以正常工作的示例,但我仍然有 0.00 + 1.00i,并且加号更接近虚部......

EDIT2: \pgfmathprintcomplexnumber 很大程度上受到 \pgfmathprintnumber 的启发。剩余问题:可能会显示 1i

答案1

当然,您需要应用“if number = 0 ... else ... endif”等条件。

如果你能做到

  1. 用于\pgfmathfloatparsenumber获取浮点格式的中间结果
  2. 用于\pgfmathfloatifflags检查数字是否为零、正数、负数、非数、inf、-inf。

这是一个例子(我简化了“合并不同的表”部分,因为它与格式化复数的任务无关):

\documentclass{standalone}
\usepackage{pgfplotstable}

\begin{document}

\pgfplotstabletypeset[
    columns/complex1/.style={string type, column name={}},
    create on use/complex1/.style={%
      create col/assign/.code={%
        \pgfmathfloatparsenumber{\thisrow{Re}}%
        \let\valueRe=\pgfmathresult
        \pgfmathfloatparsenumber{\thisrow{Im}}%
        \let\valueIm=\pgfmathresult
        \pgfmathfloatifflags{\valueRe}{0}{%
            % Ah: re = 0.0
            \def\valueRe{}%
        }{%
            \edef\valueRe{\noexpand\pgfmathprintnumber[fixed zerofill]{\valueRe}}%
        }%
        %\show\valueRe
        \pgfmathfloatifflags{\valueIm}{0}{%
            % Ah - im = 0.0
            \def\valueIm{}%
        }{%
            \edef\valueIm{\noexpand\pgfmathprintnumber[showpos,fixed zerofill]{\valueIm}i}%
        }%
        %\show\valueIm
        \toks0=\expandafter{\valueRe}%
        \toks1=\expandafter{\valueIm}%
        % we cannot use \edef\value{\valueRe\valueIm} as this would
        % expand \pgfmathprintnumber - which is not expandable.
        % Writing \the<tokenregister> expands the content of
        % <tokenregister> exactly once:
        \edef\value{\the\toks0 \the\toks1 }%
        %\show\value
        \pgfkeyslet{/pgfplots/table/create col/next content}\value
      }
    },
    %debug,
    columns={complex1},
]{
  Re                Im
  1.0000000e+00     0.0000000e+00
  5.0000000e-01     5.0000000e-01
  0.0000000e+00     1.0000000e+00
  5.0000000e-01     5.0000000e-01
}

\end{document}

在此处输入图片描述

参考文献:引用自 tikz 手册pgfmanual.pdf

\pgfmathfloatifflags{ floating point number }{ flag }{ true-code }{ false-code }
    Invokes { true-code } if the flag of { floating point number } equals { flag } and { false-code } other-
    wise.
    The argument { flag } can be one of
    0 to test for zero,
    1 to test for positive numbers,
    + to test for positive numbers,
    2 to test for negative numbers,
    - to test for negative numbers,
    3 for "not-a-number",
    4 for +infty,
    5 for -infty.

在我的文档中提到了 token-register 的魔法我应该从哪里开始 LaTeX 编程?


答案的下一部分是关于对齐的。乍一看似乎很有用,但实际上它不必要地复杂,因为只需分别排版“Re”和“Im”就可以轻松完成对齐。尽管如此,它还是有效的,并且可能有助于了解如何采用这些东西。

将这部分视为“高级用户的练习”。

这里有一个修改(仅在两个地方,在\edef\value和中column type),它使实部和虚部之间的结果对齐:

\documentclass{standalone}
\usepackage{pgfplotstable}

\begin{document}

\pgfplotstabletypeset[
    columns/complex1/.style={string type, column type={r@{}l},column name={}},
    create on use/complex1/.style={%
      create col/assign/.code={%
        \pgfmathfloatparsenumber{\thisrow{Re}}%
        \let\valueRe=\pgfmathresult
        \pgfmathfloatparsenumber{\thisrow{Im}}%
        \let\valueIm=\pgfmathresult
        \pgfmathfloatifflags{\valueRe}{0}{%
            % Ah: re = 0.0
            \def\valueRe{}%
        }{%
            \edef\valueRe{\noexpand\pgfmathprintnumber[fixed zerofill]{\valueRe}}%
        }%
        %\show\valueRe
        \pgfmathfloatifflags{\valueIm}{0}{%
            % Ah - im = 0.0
            \def\valueIm{}%
        }{%
            \edef\valueIm{\noexpand\pgfmathprintnumber[showpos,fixed zerofill]{\valueIm}i}%
        }%
        %\show\valueIm
        \toks0=\expandafter{\valueRe}%
        \toks1=\expandafter{\valueIm}%
        % we cannot use \edef\value{\valueRe\valueIm} as this would
        % expand \pgfmathprintnumber - which is not expandable.
        % Writing \the<tokenregister> expands the content of
        % <tokenregister> exactly once:
        \edef\value{\the\toks0 & \the\toks1 }%
        %\show\value
        \pgfkeyslet{/pgfplots/table/create col/next content}\value
      }
    },
    %debug,
    columns={complex1},
]{
  Re                Im
  1.0000000e+00     0.0000000e+00
  5.0000000e-01     5.0000000e-01
  0.0000000e+00     1.0000000e+00
  5.0000000e-01     5.0000000e-01
}

\end{document}

在此处输入图片描述

相关内容