我希望构建一个 (简单的) abs 实现。我试过了,\FPabs
但小数点后有很多零。我可以用 FP 舍入函数去掉它们,但我不知道小数点后会有多少个零。
我认为字符串操作方法更好。我可以使用xstring
包来去除减号,例如 -12.3 得到 12.3,但为此需要一个完整的包...
是否有一种简单的方法可以摆脱或消耗“-12.3”中的“-”例如得到“12.3”?
答案1
你可以\gobbleminus
通过这种方式定义:
\def\gobbleminus#1{\ifx-#1\else#1\fi}
%test:
\gobbleminus -12
\gobbleminus 1234
\gobbleminus .24
答案2
您可以使用 xfp (该包很短,它只包含两个用于创建包装器的定义\fp_eval:n
和\int_eval:n
):
\documentclass{article}
\usepackage{xfp}
\begin{document}
\fpeval{abs(-12.3)}
\end{document}
它是可扩展的,这意味着您可以将其输入\num
进行格式化。在这里我将句点更改为命令:
\documentclass{article}
\usepackage{xfp,siunitx}
\sisetup{locale=DE}
\begin{document}
\num{\fpeval{abs(-12.3)}}
\end{document}
答案3
我相信您很快就会从一位专家那里得到一个 LaTeX3 解决方案,而且我真的不认为基于字符串的解决方案是您能做的最好的事情,但是在您等待的时候,这里有一个简单的、基于参数的解决方案。
该解决方案不可扩展,这可能会成为您想要做的事情(但:请参见下文)。
主要思想是使用分隔参数(TeX 如何查找分隔参数?) 从字符串中删除字符。为了避免在这里遇到麻烦,我们首先检查字符是否确实存在。
\ifstrstartswith
通过定义一个辅助宏\fstr@ifstrstartswith@i
来抓取参数,如下所示
#1<characters to find>#2&
\fstr@ifstrstartswith@i
如果我们现在将一个以 开头的字符串传递给<characters to find>
,TeX 的参数解析规则会使其#1
为空。为了避免错误,我们总是\fstr@ifstrstartswith@i
使用 来调用\fstr@ifstrstartswith@i <string><characters to find>&
。这意味着即使根本<string>
不包含<characters to find>
,我们仍然使用正确的参数签名调用了宏。
字符剥离现在的工作方式类似。我们检查<string>
实际以 开头,然后应用带有签名的<characters to remove>
辅助宏\fstr@stripfromstart@i
<characters to remove>#1&
然后当被调用时,<characters to remove>
从 的开头剥离。<string>
\fstr@stripfromstart@i <string>&
\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{etoolbox}
\makeatletter
% {<characters to find>}{<string>}
\newrobustcmd*{\ifstrstartswith}[2]{%
\def\fstr@ifstrstartswith@i##1#1##2&{%
\ifblank{##1}}%
\fstr@ifstrstartswith@i#2#1&}
% {<characters to remove>}{<string>}
\newrobustcmd*{\stripfromstart}[2]{%
\def\fstr@stripfromstart@i#1##1&{##1}%
\ifstrstartswith{#1}{#2}
{\fstr@stripfromstart@i#2&}
{#2}}
\makeatother
\newcommand*{\mysimpleabs}{\stripfromstart{-}}
\begin{document}
\mysimpleabs{4.5}
\mysimpleabs{-4.5}
\end{document}
当然,你不想尝试\mysimpleabs{-4.5-5}
或\mysimpleabs{-4.5+5}
。
编辑仔细想想,如果我们对 进行硬编码,就可以使其可扩展-
。不过,我认为字符串操作并不是处理此问题的最佳方法。
\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{etoolbox}
\makeatletter
\newcommand*{\fstr@ifstrstartswithminus@i}{} % just to reserve the name
\def\fstr@ifstrstartswithminus@i#1-#2&{\ifblank{#1}}
\newcommand*{\ifstrstartswithminus}[1]{%
\fstr@ifstrstartswithminus@i#1-&}
\newcommand*{\fstr@stripminusfromstart@i}{} % just to reserve the name
\def\fstr@stripminusfromstart@i-#1&{#1}
\newcommand*{\stripminusfromstart}[1]{%
\ifstrstartswithminus{#1}
{\fstr@stripminusfromstart@i#1&}
{#1}}
\makeatother
\newcommand*{\mysimpleabs}{\stripminusfromstart}
\begin{document}
\mysimpleabs{4.5}
\mysimpleabs{-4.5}
\edef\foo{\mysimpleabs{12.3}}
\meaning\foo
\edef\foo{\mysimpleabs{-12.3}}
\meaning\foo
\end{document}
答案4
如果你知道要去掉减号的东西以减号或数字开头,那么老套这样做的方法是
\makeatletter
\def\gobbleminus#1{\ifnum#17<\z@ \@firstoftwo\fi #1}
\makeatother
例如
\gobbleminus 12.3 % Expands to 12.3
\gobbleminus -12.3 % Expands to 12.3
\gobbleminus -0.1000 % Expands to 0.1000
如果您的数据是通过扩展某些东西生成的,那么您当然需要确保它在让 \gobbleminus 对其采取行动之前得到充分扩展。
另一个问题是
\gobbleminus .123 % Raises error
因为 . 不是减号或数字。不过我想到也可以让它容忍这种情况,只需将定义改为
\makeatletter
\def\gobbleminus#1{\ifdim#17pt<\z@ \@firstoftwo\fi #1}
\makeatother