通过删除或消耗“-”来简单实现 abs 功能?

通过删除或消耗“-”来简单实现 abs 功能?

我希望构建一个 (简单的) 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}

4.5//4.5

当然,你不想尝试\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

相关内容