11

I want to compare the output of \ref to a number in LaTeX. I thought it would be easy but after spending lots of hours surfing the net I still don't know the answer.
I found similar questions on this site but I would prefer a solution that does not require another package to be included, so that I can see clearly how the \ref command (and some others) works.
I tried a lot of things, some of which I share below, therefore my question is rather long, I'm sorry about that.
First, I tried the following codes (the resulting error messages are shown after a % sign):

\begin{equation} \label{eq:myeq}  
a=b  
\end{equation}

\ifnum\ref{eq:myeq}=1 true\else false\fi % error: "Missing number, treated as zero."

\expandafter\ifnum\ref{eq:myeq}=1 true\else false\fi % error: "Missing number, treated as zero."

\edef\blabla{\ref{eq:myeq}} % error: Incomplete \iffalse; all text was ignored after line 42.
\ifnum\blabla=1 true\else false\fi
\expandafter\ifnum\blabla=1 true\else false\fi

Of course, \ref{eq:myeq} gave the expected result, namely 1.

Then, I found the definition of \ref using the latexdef ref command:

\ref:
macro:#1->\expandafter \@setref \csname r@#1\endcsname \@firstoftwo {#1}

Further examining \@setref and \firstoftwo, I concluded that the equation number (together with the page number) is stored in a control sequence called \r@eq:myeq. More precisely, the content of \r@eq:myeq is {1}{1} where the first number is the equation number and the second number is the page number. (The output of \expandafter{\csname r@eq:myeq\endcsname} is 11.) If I understand well, in order to obtain the equation number we have to expand \csname r@eq:myeq\endcsname by only two levels to get {1}{1} (the first level of expansion yields \r@eq:myeq), and then we choose the first argument by \@firstoftwo. Since there is no simple way to expand a control sequence by only one level, it is done in a rather circuitous (say tricky) way by \ref. This I could also reproduce by the following code:

\def\sth#1#2{\expandafter #2#1}
\makeatletter
\expandafter\sth\csname r@eq:myeq\endcsname\@firstoftwo \quad
\ifnum1=\expandafter\sth\csname r@eq:myeq\endcsname\@firstoftwo true\else false\fi
\makeatother

which resulted in 1 true.
So far so good but there are still a few questions. First of all, if the above code works then why does the code with \ifnum1=\ref{eq:myeq}... fail (see above)? Seemingly, the two "algorithms" are doing the same.
Second, the above code works only if the auxiliary file (with aux extension) contains the label definition. If it doesn't (the reference is undefined) then LaTeX gives the following error message: Missing number, treated as zero. How can I write a code that works even if the reference is undefined?
Thank everybody who read all my above struggle and I would appreciate if someone shed light on the points that were not clear to me and who corrected me where I was wrong and confirmed where I was correct. Unfortunately the whole command syntax of (La)TeX is still very strange to me.

  • I found out that if I define a macro (say \myref) exactly the same way as \ref is defined according to several sources (e.g. output of latexdef ref, latex.ltx on my computer, source2e.pdf), that is I write \def\myref#1{\expandafter\@setref\csname r@#1\endcsname\@firstoftwo{#1}} in my code, then the output of \myref can be compared to a number using \ifnum (if the reference is defined). Can anybody explain this? With all my thanks to @Werner and @Steven, I think that this is the easiest solution. – Gabor Jan 30 '15 at 7:22
12

This is exactly what refcount was made for, and there's no need to re-invent the wheel here. It provides \getrefnumber as an expandable macro that you can use in calculations:

enter image description here

\documentclass{article}

\usepackage{refcount}

\begin{document}

\begin{equation} \label{eq:myeq}  
  a=b  
\end{equation}

\ifnum\getrefnumber{eq:myeq}=1 true\else false\fi %true

\end{document}

If you really don't want any packages, extract the relevant macros from refcount's source, and add this to your preamble:

\makeatletter
\newcommand*{\getrefnumber}[1]{%
  \romannumeral
  \@ifundefined{r@#1}{%
    \expandafter\ltx@zero
    \rc@default
  }{%
    \expandafter\expandafter\expandafter\rc@extract@
    \expandafter\expandafter\expandafter!%
    \csname r@#1\expandafter\endcsname
    \expandafter{\rc@default}\@nil
  }%
}
\def\rc@default{0}%
\long\def\rc@extract@#1#2#3\@nil{%
  \ltx@zero
  #2%
}
\chardef\ltx@zero=0
\makeatother
  • Would someone explain what the \romannumeral is doing here? Does this have some option to output roman numerals? – Richard Birkett Sep 9 at 1:13
  • @RichardBirkett: This deals with expansion, I imagine. However, I'm not entirely sure. You should ask a follow-up question. – Werner Sep 9 at 15:18
6

Using stringstrings

\documentclass{article}
%\usepackage{amsmath}
\usepackage{stringstrings}
\newcounter{myctr}
\newcommand\cmpeq[2]{%
  \substring[e]{\ref{#1}}{1}{$-2}%
  \setcounter{myctr}{\thestring}%
  \ifnum\value{myctr}=#2 T\else F\fi%
}
\begin{document}
\begin{equation} \label{eq:myeq}  
a=b  
\end{equation}
\cmpeq{eq:myeq}{0}
\cmpeq{eq:myeq}{1}
\cmpeq{eq:myeq}{2}

\begin{equation} \label{eq:myeqA}  
c=d  
\end{equation}
\cmpeq{eq:myeqA}{0}
\cmpeq{eq:myeqA}{1}
\cmpeq{eq:myeqA}{2}
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.