经过数小时的实验和研究,我仍然无法弄清楚如何在两个数字之间执行简单的相等性测试。
更具体地说,这里所讨论的两个数字是我的\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}
编辑:直接回答 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。如果尝试使用更大的值,
\maxdimen
TeX 将会报错。! 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}
与简单的方法相反\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 部分。
答案4
要比较任意大的十进制有理数(例如3.141592
与2.1782817828
),您可以使用包信特压裂。
特别是因为1.09a (2013/09/24)
它提供了\xintifEq{A}{B}{<do this if A=B>}{<do that if A\neq B>}
。
这里的A
和B
可能是(大)整数、小数(带有科学计数法部分)、或分数,或者扩展为这些东西的宏。
\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}
原始答案(添加\xintifEq
之前xintfrac
)
\xintCmp{A}{B}
返回-1
,0
,或1
如果A<B
,A=B
,A>B
。A
和B
可能是十进制数,分数,或扩展为这些东西的宏。
并且\xintSgnFork{\x}{I}{II}{III}
如果I
扩展\x
为-1
,II
如果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}