如何比较两个(不一定是整数)变量?

如何比较两个(不一定是整数)变量?

经过数小时的实验和研究,我仍然无法弄清楚如何在两个数字之间执行简单的相等性测试。

更具体地说,这里所讨论的两个数字是我的\abc命令的参数(#1)和我的\test变量。

这是我所想到的,但它并没有产生预期的结果:

\documentclass{article}

\begin{document}
\def\test{0.5}

\newcommand{\abc}[1]{
\ifnum #1=\test
  Something % do something
\fi}

\abc{0.5} % does something
\abc{0.7} % does nothing

\end{document}

请帮助我解决这个问题。

答案1

\ifnum可用于比较数字,但前提是后者是整数。但是,您可以使用\ifdim比较定点数。请注意,您需要指定一些单位(例如pt)。

您可能需要一个更通用的命令,例如我在下面定义的命令(\equalitytest),它比较两个任意定点数的值。您可以随时\abc根据我的\equalitytest命令定义您的命令。

\documentclass{article}

\setlength{\parindent}{0pt}

\newcommand\equalitytest[2]
{%
    Is #1\ equal to #2?
    \ifdim#1pt=#2pt
        Equal.\\
    \else%
        Not equal.\\
    \fi%
}

\begin{document} 
\equalitytest{0.5}{0.5}
\equalitytest{0.7}{.8}

\def\test{0.5}
\newcommand\abc[1]
{%
    \equalitytest{#1}{\test}
}
\abc{0.9}
\end{document}

enter image description here


编辑:直接回答 Pygmalion 的帖子:

\documentclass{article}

\begin{document}
\def\test{0.5}

\newcommand{\abc}[1]{
\ifdim#1 pt=\test pt
  Something % do something
\fi}

\abc{0.5} % does something
\abc{0.7} % does nothing

\end{document}

答案2

Jubobs 的回答显示了如何使用 TeX 维度来比较定点数。有两个限制:

  • TeX 的最大尺寸为= 16383.99998pt = 16384pt - 1sp。如果尝试使用更大的值,\maxdimenTeX 将会报错。! Dimension too large
  • 最小的 TeX 尺寸是 1sp = 2 -16 pt ≈ 0.00001525878906pt。

正如 jfbu 在评论,由于 TeX 对数字的扫描,小数部分被四舍五入为 2 -16 ≈ 0.000015258789的倍数,因此最大单位的in小数部分不会比标准单位具有更高的精度。pt

另一个极端是sp忽略小数部分的单位。但数字最高可达 2 30 -1 = 1073741824。

包裹fp

软件包fp实现了基于宏的定点算法。从其readme

Fixed point arithmetic for TeX with numbers ranging from
   -999999999999999999.999999999999999999
to
   +999999999999999999.999999999999999999

下面的示例使用包实现定点数的比较fp

\documentclass{article}

\usepackage{fp-basic}
\makeatletter
% \equalnumsthenelse{<number A>}{<number B>}{<then: A=B>}{<else: A≠B>}
\newcommand*{\equalnumsthenelse}[2]{%
  \FPifeq{#1}{#2}%
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\makeatother

\begin{document}
\def\test{0.5}

\newcommand*{\abc}[1]{
  \equalnumsthenelse{#1}{\test}{%
    \[#1=\test\]%
  }{%
    \[#1\ne\test\]%
  }%
}

\abc{0.5}
\abc{0.7}
\abc{0.500000000001}
\abc{1234567890}

\end{document}

Result

与简单的方法相反\ifdim,该方法不具有扩展性,因为\FPifeq

答案3

需要考虑的替代方案是l3fp,包含在内expl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\fpcompare}{ m m m }
 {
  % #1 = test to perform
  % #2 = text for the true case
  % #3 = text for the false case
  \fp_compare:nTF { #1 } { #2 } { #3 }
 }
\ExplSyntaxOff

\newcommand\test{0.5}
\newcommand{\abc}[1]{%
  \fpcompare{#1=\test}{Something}{}%
}

\begin{document}
\verb|\abc{0.5}|: X\abc{0.5}X

\verb|\abc{0.7}|: X\abc{0.7}X

\verb|\abc{0.500000000001}|: X\abc{0.500000000001}X

\verb|\abc{1234567890}|: X\abc{1234567890}X

\edef\TEST{\fpcompare{0.5 = 0.5}{Equal}{Different}}\texttt{\meaning\TEST}\\
\TEST

\edef\TEST{\fpcompare{0.7 = .8}{Equal}{Different}}\texttt{\meaning\TEST}\\
\TEST

\fpcompare{3.141529653 = 355/113}{Equal}{Different}

\fpcompare{3.141529653 != 355/113}{Different}{Equal}

\fpcompare{2.718281828459045 = 2718.281828459045/1000}{Equal}{Different}

\end{document}

可以测试是否与 相等,是否与或<fp1> = <fp2>严格不等,是否与或非严格不等,是否与 不等。<fp1> < <fp2><fp1> > <fp2><fp1> <= <fp2><fp1> >= <fp2><fp1> != <fp2>

在示例代码中,我展示了测试是完全可扩展的。interface3.pdf有关语法<fp>和大小限制的更多信息,请参阅第 XXI 部分。

enter image description here

答案4

要比较任意大的十进制有理数(例如3.1415922.1782817828),您可以使用包信特压裂

特别是因为1.09a (2013/09/24)它提供了\xintifEq{A}{B}{<do this if A=B>}{<do that if A\neq B>}

这里的AB 可能是(大)整数、小数(带有科学计数法部分)、或分数,或者扩展为这些东西的宏。

\documentclass{article}
\usepackage{xintfrac}

\newcommand*\equalitytest[2]{%
    \xintifEq{#1}{#2}{#1 is equal to #2}{#1 is unequal to #2}%
}%

\begin{document}

\equalitytest{3.141529653}{355/113}

\equalitytest{2.718281828459045}{2718.281828459045/1000}

\end{document}

enter image description here


原始答案(添加\xintifEq之前xintfrac

\xintCmp{A}{B}返回-10,或1如果A<BA=BA>BAB可能是十进制数,分数,或扩展为这些东西的宏。

并且\xintSgnFork{\x}{I}{II}{III}如果I扩展\x-1II如果0,并且III如果1

\documentclass{article}
\usepackage{xintfrac}

% arguments may be decimal numbers such as 3.14
% or fractions such as 355/113

% this is an expandable command
% (its arguments may be macros expanding to the numbers or fractions)

\newcommand*\equalitytest[2]{%
    \xintSgnFork{\xintiAbs{\xintCmp{#1}{#2}}}% -1 converted into 1
    {}% -1: does not happen
    {equal}%   \xintCmp returned 0
    {unequal}% \xintCmp returned -1 or 1.
}%

\begin{document}

\equalitytest{3.141529653}{355/113} (355/113=\xintTrunc{10}{355/113}...) %unequal

\equalitytest{2.718281828459045}{2718.281828459045/1000} % equal


\end{document}

comparison

相关内容