我的论文包括诸如 、9.368e-03
或 之类的数字9.368E-03
,它们遍布正文。我想以科学记数法的形式排版它们,例如 - 9.683 x 10^-3
。
但是,由于我正在使用TeX Live 2009在同样古老的机器上,由于我的论文文档已经变得相当大,我不想通过使用任何专用包(例如siunitx
)来增加系统负担,只是为了正确排版几个数字。
有没有更简单的方法可以让我以所需的格式排版数字,而无需使用专门的科学计数法包?
答案1
对于给定的简单格式,一小段专用命令就可以获取数字。我在这里假设这些数字对于 TeX 的\number
基元来说永远不会有太多的数字,我用它来修剪任何前导零。
\documentclass{article}
\makeatletter
\newcommand*{\num}[1]{%
\ensuremath{%
\num@auxi#1ee\stop
}%
}
\newcommand*\num@auxi{}
\def\num@auxi#1e#2e#3\stop{%
\ifx\relax#2\relax
\expandafter\num@auxii
\else
\expandafter\num@auxv
\fi
{#1}{#2}%
}
\newcommand*\num@auxii[2]{%
\num@auxiii#1EE\stop
}
\newcommand*\num@auxiii{}
\def\num@auxiii#1E#2E#3\stop{%
\ifx\relax#2\relax
\expandafter\num@auxiv
\else
\expandafter\num@auxv
\fi
{#1}{#2}%
}
\newcommand*\num@auxiv[2]{%
\number #1
}
\newcommand*\num@auxv[2]{%
\number #1 \times 10^{\number #2 }%
}
\makeatother
\begin{document}
\num{9.386e-03}
\num{9.386E-03}
\num{9.386}
$\num{9.386e-03}$
\end{document}
如果你想保留前导零和任何前导+
符号,代码可以稍微简化
\documentclass{article}
\makeatletter
\newcommand*{\num}[1]{%
\ensuremath{%
\num@auxi#1ee\stop
}%
}
\newcommand*\num@auxi{}
\def\num@auxi#1e#2e#3\stop{%
\ifx\relax#2\relax
\expandafter\num@auxii
\else
\expandafter\num@auxiv
\fi
{#1}{#2}%
}
\newcommand*\num@auxii[2]{%
\num@auxiii#1EE\stop
}
\newcommand*\num@auxiii{}
\def\num@auxiii#1E#2E#3\stop{%
\ifx\relax#2\relax
\expandafter\@firstoftwo
\else
\expandafter\num@auxiv
\fi
{#1}{#2}%
}
\newcommand*\num@auxiv[2]{%
#1 \times 10^{#2}%
}
\makeatother
\begin{document}
\num{9.386e-03}
\num{9.386E-03}
\num{9.386}
$\num{9.386e-03}$
\end{document}
更复杂的解析是可能的siunitx
,而不需要使用numprint
这个软件包中提供了相当多这样的功能,并且这个软件包已经使用了很多年。
上面的代码是如何工作的?外部宏
\newcommand*{\num}[1]{%
\ensuremath{%
\num@auxi#1ee\stop
}%
}
只需抓取整个输入,并将其插入到第一个内部宏之后\num@auxi
。后者将寻找一个e
,因此我们确保在ee
输入后包含一个。(稍后我会回来解释为什么是两个e
标记。)
\num@auxi
接下来是宏观
\def\num@auxi#1e#2e#3\stop{%
\ifx\relax#2\relax
\expandafter\num@auxii
\else
\expandafter\num@auxv
\fi
{#1}{#2}%
}
这里我们有一个分隔宏。第一个之前的所有内容都e
将被抓取为 ,介于 和第二个之间的所有内容将被抓取为,#1
直到的余数将被抓取为。结果有两种。如果原始输入包含 ,则将是尾数,将是指数并且是垃圾。另一方面,如果没有 ,则是整个数字并且为空。我们使用(如果为空则为真)进行测试并相应地进行分支。e
#3
\stop
#3
e
#1
#2
#3
e
#1
#2
\ifx\relax#2\relax
#2
如果e
没有找到,则需要进行一些设置以再次执行相同的操作,但要寻找E
。搜索完成后,我们有两个结果:一个没有指数的数字或一个有指数的数字。第一种情况由
\newcommand*\num@auxiv[2]{%
\number #1
}
由于我设置代码的方式,它接收两个参数,尾数和指数。我们知道后者是空的(它只是作为“丢弃”的),所以我们只需插入#1
(尾数)。我在\number
它前面已经包含了,这意味着 TeX 将“整理”输入,删除任何前导零或+
符号。
如果有指数,则代码
\newcommand*\num@auxv[2]{%
\number #1 \times 10^{\number #2 }%
}
被使用:这会插入尾数,然后插入格式正确的指数。我本可以将最后两个宏组合起来,并在#2
其中进行测试,但我觉得使用单独的路径会更清晰。
你可能会想知道为什么我们
\def\num@auxi#1e#2e#3\stop{%
而不是只使用一个e
(因为输入只能有一个)。这一切都归结为使测试尽可能短。使用定义
\def\num@auxi#1e#2\stop{%
你可能会认为我们会没事的。然而,有一个问题。如果我这样做
\num@auxi#1\stop
e
并且输入中没有,那么 TeX 会抱怨,因为的参数\num@auxi
无法正确匹配。因此我们需要这样做
\num@auxi#1e\stop
以确保始终有一个e
要查找的。但是,如果输入还包含一个,e
则\num@auxi
最终会分裂,因此#1
是尾数,但#2
指数加上尾随的。我们可以允许这样做,这将是一个清理步骤,但使用两个标记并使用定义e
更容易e
\def\num@auxi#1e#2e#3\stop{%
用作
\num@auxi#1ee\stop
e
在这种情况下,如果输入中没有,我们将得到#1
尾数,而#2
和#3
为空。另一方面,如果e
输入中有,那么#1
就是尾数,#2
是指数,并#3
清除杂散e
(我们总是丢弃#3
)。所以以这种方式工作,我们只需要一个宏来完成工作。
答案2
此解决方案基于xstring
包的\StrSubstitute
命令。它替换每个出现的X
从选定的字符串元素中Y
。定义了一个新命令,用于从输入数字(或)中\StrSubstitute
删除e
或,并将其排版为科学计数法的形式,即。其余的是不言自明的。E
9.368e-03
9.368E-03
1.536×10^-01
注1: 如果用户忘记写 e
或者 E
在输入中,此方法依然有效!
笔记2: 对于包含的数字 E
代替 e
,用户必须使用 \sciE
方法。第一种方法,即 \sci
在这种特殊情况下将会失败!
免责声明:这只是将数字排版为科学计数法的众多方法之一。此外,此解决方案基于可以接受一些手工劳动的假设!
最小工作示例:
\documentclass{article}
\usepackage{booktabs}
\usepackage{xstring} % for text replacement
\usepackage{xcolor}
\providecommand{\sci}[1]{\protect\ensuremath{\times 10^{\StrSubstitute[0]{#1}{e}{}}}}
% ---- for numbers in format: 9.368e-03 (i.e., numbers using e)
% \sci will remove "e" from the input and typeset the result as:- \times 10^
% \StrSubstitute[0]{#1}{e}{} from the command substitutes "e" by nothing i.e. null!
% usage: if 1.536e-01 is to be converted then -- 1.536\sci{e-01} gives 1.536×10^-01
\providecommand{\sciE}[1]{\protect\ensuremath{\times 10^{\StrSubstitute[0]{#1}{E}{}}}}
% ---- for numbers in format: 9.368E-03 (i.e., numbers using E)
\begin{document}
{\noindent\Large 1.536e-01 is the input number, which we would like to\\[8pt]
convert to a number in scientific notation, like so \textemdash}\\[0.35in]
%
\hspace*{\fill}{\huge \fcolorbox{cyan!25}{cyan!15}{1.536\sci{e-01}}}\hspace*{\fill}
\vspace*{0.3in}
{ % Begin group -- To keep the effect local!
\renewcommand*{\arraystretch}{1.75}
\begin{table}[h]
\large
\begin{center}
\begin{tabular}{@{\extracolsep{\fill}}@{\hskip 3em}c@{\hskip 6em}c@{\hskip 3em}@{}}
\toprule
\textbf{qValue} & \textbf{qValueRes}\\
\midrule
9.368\sci{e-03} & 2.180\sci{e-02} \\
1.058\sci{e-06} & 1.411\sci{e-03} \\
2.563\sci{e-02} & 5.281\sci{e-02} \\
\colorbox{gray!50}{1.536e-01} & \colorbox{gray!50}{1.536e-01} \\ % original numbers!
\colorbox{gray!50}{1.536e-01} & \colorbox{gray!50}{1.536e-01} \\ % original numbers!
1.536\sci{e-01} & 1.536\sci{e-01} \\
2.563\sci{e-02} & 5.281\sci{e-02} \\
\bottomrule
\end{tabular}
\end{center}
\caption{Test}
\label{tab:test}
\end{table}
} % End group -- To keep the effect local!
\end{document}
MWE 输出: