How can I compare two (not necessarily integer) variables?

\ifnum can be used to compare numbers, but only if the latter are integers. However, you can use \ifdim to compare fixed-point number. Note that you need to specify some unit (such as pt), though.

You probably want a more general command like the one I've defined below (\equalitytest), which compares the values of two arbitrary fixed-point numbers. You can always define your \abc command based on my \equalitytest command.

\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


Edit: Direct answer to Pygmalion's post:

\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}

Jubobs answer shows, how TeX dimensions can be used to compare fixed point numbers. There are two limitations:

  • The largest TeX dimension is \maxdimen = 16383.99998pt = 16384pt - 1sp. TeX will complain with ! Dimension too large, if larger values are tried.
  • The smallest TeX dimension is 1sp = 2-16pt ≈ 0.00001525878906pt.

As jfbu pointed out in the comment, the largest unit in does not give an higher precision for the fractional part than the standard unit pt because of the rounding of the fractional part to multiples of 2-16 ≈ 0.000015258789 due to TeX's scanning of the number.

The other extreme is unit sp that ignores the fractional part. But the number can go up to 230-1 = 1073741824.

Package fp

Package fp implements macro based fixed point arithmetic. From its readme:

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

The following example implements the comparison of fixed point numbers using package 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

In opposite to a simple \ifdim, this method is not expandable because of \FPifeq.


An alternative to be considered is l3fp, included in 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}

One can test for equality with <fp1> = <fp2>, strict inequality with <fp1> < <fp2> or <fp1> > <fp2>, non strict inequality with <fp1> <= <fp2> or <fp1> >= <fp2>, inequality with <fp1> != <fp2>.

In the example code, I show that the test is fully expandable. Consult interface3.pdf, part XXI for more information about the syntax of <fp> and size limitations.

enter image description here

Tags:

Tex Core