Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

memoir's \checkifinteger

36 views
Skip to first unread message

Rasmus Villemoes

unread,
Oct 18, 2010, 11:14:06 AM10/18/10
to
I have a macro whose argument must be a number (in fact, it should
represent a year). I allow both two- and four-digit numbers, and I
have some code which correctly converts a twodigit argument to a year
in the range 1950-2049.

So far, this has mostly been for private use, but I plan to put this
in a package for distribution. Hence, I would like to test if #1 is an
integer, and googling found the FAQ answer
http://www.tex.ac.uk/cgi-bin/texfaq2html?label=isitanum. This led me
to look in memoir.cls, where one finds


\newcommand{\checkifinteger}[1]{%
\protected@edef\@vsa{#1}%
\ifcat _\ifnum9<1\gobm{#1} _\else A\fi
\integertrue%
\else
\integerfalse%
\fi}
\newcommand{\gobm}[1]{#1}

I was hoping someone could explain how this works. The main part of
the code is similar to the other solutions mentioned in the FAQ. As
far as I can see, one compares the category code of _ with that of
either _ or A, depending on whether concatenating 1 and #1 produces a
number which is greater than 9. But:

* Why is the \gobm used/needed? [1]

* What does the \protected@edef do? \@vsa is not mentioned anywhere
else in memoir.cls. Does it give a "better" error message if #1
happens to contain "bad stuff"?

I was thinking of simply copying the above code (first checking
\@ifclassloaded{memoir}), but I would like to know how it works before
doing so.

Is there an expl3 solution?


[1] A somewhat unrelated remark: I'm also wondering why \memjustarg is
not used; it has the exact same definition (although in the manual
it is stated that it is defined using \newcommand*)

--
Rasmus Villemoes
<http://rasmusvillemoes.dk/>

zappathustra

unread,
Oct 18, 2010, 11:40:38 AM10/18/10
to
Le 18/10/2010 17:14, Rasmus Villemoes a �crit :

> \newcommand{\checkifinteger}[1]{%
> \protected@edef\@vsa{#1}%
> \ifcat _\ifnum9<1\gobm{#1} _\else A\fi
> \integertrue%
> \else
> \integerfalse%
> \fi}
> \newcommand{\gobm}[1]{#1}
>
> I was hoping someone could explain how this works. The main part of
> the code is similar to the other solutions mentioned in the FAQ. As
> far as I can see, one compares the category code of _ with that of
> either _ or A, depending on whether concatenating 1 and #1 produces a
> number which is greater than 9.

Yes. And as a solution, it is not perfect because \checkifinteger{1?}
will return true. Plus a space and a question mark before that. Using
\if would at least reduce the risk to \checkifinteger{1_}. But I suppose
the macro is only used in some very specific contexts where there's no
such risk.

> But:
>
> * Why is the \gobm used/needed? [1]

You can read in memoir.dtx that \gobm is a placeholder for \gobbleminus
(shown in the faq). It can be \let to that command, but if you don't
want to, it simply does nothing. The reason is probably to switch
between a check for positive integers and a check for any integer.

> * What does the \protected@edef do? \@vsa is not mentioned anywhere
> else in memoir.cls. Does it give a "better" error message if #1
> happens to contain "bad stuff"?
>

Well, that I don't know.

> I was thinking of simply copying the above code (first checking
> \@ifclassloaded{memoir}), but I would like to know how it works before
> doing so.

Beware, as I've said above, this command should be used in special
contexts only. Chaos is not far away.
There's no real integer test in TeX.

> Is there an expl3 solution?
>
>
> [1] A somewhat unrelated remark: I'm also wondering why \memjustarg is
> not used; it has the exact same definition (although in the manual
> it is stated that it is defined using \newcommand*)

You mean instead of \gobm? Because \gobm is meant to be redefined if
necessary, not \memjustarg.


Paul

GL

unread,
Oct 18, 2010, 11:41:22 AM10/18/10
to
Le 18/10/2010 17:14, Rasmus Villemoes a �crit :

ideed, that's weird !
there is another solution to check if a parameter is a integer,
using a trick close to \@defaultunits...

zappathustra

unread,
Oct 18, 2010, 12:01:50 PM10/18/10
to
Le 18/10/2010 17:40, zappathustra a �crit :

> Le 18/10/2010 17:14, Rasmus Villemoes a �crit :
>
>> I was thinking of simply copying the above code (first checking
>> \@ifclassloaded{memoir}), but I would like to know how it works before
>> doing so.
>
> Beware, as I've said above, this command should be used in special
> contexts only. Chaos is not far away.
> There's no real integer test in TeX.

Hmmm, I made myself think, though.
Could a wizard inspect this?

\newcount\trialcount
\def\checkifinteger#1{%
\def\temp{#1}%
\ifx\temp\empty \integerfalse
\else \afterassignment\checkrest\trialcount=1#1 \endoftest \fi
}
\def\checkrest#1\endoftest{%
\def\temp{#1}%
\ifx\temp\empty \integertrue
\else \integerfalse\fi
}

Caveat: the test returns false if the argument to \checkifinteger is
e.g. "5 " (with a space), but the argument could be trimmed. And of
course, things might be expanded that you don't want to.

And now here comes a solid solution with LuaTeX:

\def\checkifinteger#1{%
\directlua{%
if tonumber("\unexpanded{#1}") then
tex.print("\luaescapestring{\noexpand\integertrue}")
else
tex.print("\luaescapestring{\noexpand\integerfalse}")
end
}%
}

The \unexpanded is here to prevent chaos, but of course it returns a
false test if, say, \mynumber, defined to "5", is passed as the argument.

Best,
Paul

Philipp Stephani

unread,
Oct 18, 2010, 12:41:07 PM10/18/10
to
Rasmus Villemoes <burner...@imf.au.dk> writes:

> Is there an expl3 solution?

None that I know, but here is a rather boring but robust solution that
works only in pdfTeX:

\def\ifnumeric#1\then{\ifnum\pdfmatch{^[0-9]+$}{#1}=1 }
\let\then\iffalse
\def\typeout{\immediate\write16}
\typeout{\ifnumeric123\then yes\else no\fi}
\typeout{\ifnumeric12x\then yes\else no\fi}

--
Change “LookInSig” to “tcalveu” to answer by mail.

GL

unread,
Oct 18, 2010, 12:41:46 PM10/18/10
to
Le 18/10/2010 18:01, zappathustra a �crit :

> Le 18/10/2010 17:40, zappathustra a �crit :
>> Le 18/10/2010 17:14, Rasmus Villemoes a �crit :

> Hmmm, I made myself think, though.


> Could a wizard inspect this?
>
> \newcount\trialcount
> \def\checkifinteger#1{%
> \def\temp{#1}%
> \ifx\temp\empty \integerfalse
> \else \afterassignment\checkrest\trialcount=1#1 \endoftest \fi
> }
> \def\checkrest#1\endoftest{%
> \def\temp{#1}%
> \ifx\temp\empty \integertrue
> \else \integerfalse\fi
> }

Other Caveat:
\let\@tempa=6

\newif\ifinteger


\def\checkifinteger#1{%
\def\temp{#1}%
\ifx\temp\empty \integerfalse
\else \afterassignment\checkrest\trialcount=1#1 \endoftest \fi
}
\def\checkrest#1\endoftest{%
\def\temp{#1}%
\ifx\temp\empty \integertrue
\else \integerfalse\fi
}

\loggingall
\checkifinteger\@tempa

\meaning\ifinteger %=> \iffalse

\stop

Philipp Stephani

unread,
Oct 18, 2010, 1:01:29 PM10/18/10
to
Rasmus Villemoes <burner...@imf.au.dk> writes:

> Is there an expl3 solution?

Now there is one :-)
Should be robust and completely expandable:

\cs_new_nopar:Nn \check_digit:n {
\bool_if:nF {
\token_if_eq_charcode_p:NN #1 0
|| \token_if_eq_charcode_p:NN #1 1
|| \token_if_eq_charcode_p:NN #1 2
|| \token_if_eq_charcode_p:NN #1 3
|| \token_if_eq_charcode_p:NN #1 4
|| \token_if_eq_charcode_p:NN #1 5
|| \token_if_eq_charcode_p:NN #1 6
|| \token_if_eq_charcode_p:NN #1 7
|| \token_if_eq_charcode_p:NN #1 8
|| \token_if_eq_charcode_p:NN #1 9
} {
0
\map_break:
}
}
\cs_new_nopar:Npn \IfNumericTF #1 {
\exp_args:Nf \tl_if_empty:nTF { \tl_map_function:nN { #1 } \check_digit:n }

Dan Luecking

unread,
Oct 18, 2010, 4:12:10 PM10/18/10
to
On Mon, 18 Oct 2010 17:40:38 +0200, zappathustra
<zappat...@free.fr> wrote:

> Le 18/10/2010 17:14, Rasmus Villemoes a �crit :
>> \newcommand{\checkifinteger}[1]{%
>> \protected@edef\@vsa{#1}%
>> \ifcat _\ifnum9<1\gobm{#1} _\else A\fi
>> \integertrue%
>> \else
>> \integerfalse%
>> \fi}
>> \newcommand{\gobm}[1]{#1}
>>
>> I was hoping someone could explain how this works. The main part of
>> the code is similar to the other solutions mentioned in the FAQ. As
>> far as I can see, one compares the category code of _ with that of
>> either _ or A, depending on whether concatenating 1 and #1 produces a
>> number which is greater than 9.
>
>Yes. And as a solution, it is not perfect because \checkifinteger{1?}
>will return true. Plus a space and a question mark before that.

It does none of that: after expanding the \ifnum we get:
\ifcat _? _\integertrue\else \integerfalse\fi
Which consumes the ? in the \ifcat test (which produces false),
discards tokens up to \else, and produces \integerfalse.

>Using
>\if would at least reduce the risk to \checkifinteger{1_}. But I suppose
>the macro is only used in some very specific contexts where there's no
>such risk.

It is already reduced to that, unless some other character
has been given category 8 (subscript). Categories 3, 4,
7 and 8 also seem suitable and provide a similar level of
safety.

>
>> * What does the \protected@edef do? \@vsa is not mentioned anywhere
>> else in memoir.cls. Does it give a "better" error message if #1
>> happens to contain "bad stuff"?
>>

The code was copied from verse.sty. Even in the verse
package \@vsa seems to be unused, but possibly it was
used at one time. It could have been used by another
macro that has since been changed, or it might have
once been used in place of #1 at a time when a different
test was used that required pre-expanding the argument.

I might have considered a method using \@ifmtarg after
expanding the argument and gobbling digits. Perhaps
something like that was once used.


Dan
To reply by email, change LookInSig to luecking

zappathustra

unread,
Oct 19, 2010, 4:46:51 AM10/19/10
to
Le 18/10/2010 22:12, Dan Luecking a �crit :

Yes, sorry. Very stupid of me, I took _ for a category-12 item (this
holds for the previous point too).
(It's actually often the case in my files.)

Paul

Heiko Oberdiek

unread,
Oct 19, 2010, 2:32:34 PM10/19/10
to
Rasmus Villemoes <burner...@imf.au.dk> wrote:

> \newcommand{\checkifinteger}[1]{%
> \protected@edef\@vsa{#1}%
> \ifcat _\ifnum9<1\gobm{#1} _\else A\fi
> \integertrue%
> \else
> \integerfalse%
> \fi}
> \newcommand{\gobm}[1]{#1}
>
> I was hoping someone could explain how this works. The main part of
> the code is similar to the other solutions mentioned in the FAQ. As
> far as I can see, one compares the category code of _ with that of
> either _ or A, depending on whether concatenating 1 and #1 produces a
> number which is greater than 9. But:
>
> * Why is the \gobm used/needed? [1]

It isn't necessary (with that definition). Perhaps the macro inventor
had used a macro instead of "#1", then it would be difficult to add a
space afterwards that ends the number. But the space isn't necessary
either, because "_" isn't expandable and also ends the number parsing.

Or \gobm originally removes an optional minus, as suggested by
zappathustra.

> * What does the \protected@edef do? \@vsa is not mentioned anywhere
> else in memoir.cls.

That line can be dropped, too.

The use of \checkifinteger is rather limited:
* Negative integers aren't detected as integers by this macro.
* All that starts with one digit is taken as integer: 0.0, 4pt, 48foo

--
Heiko Oberdiek

Lars Madsen

unread,
Oct 19, 2010, 2:30:33 PM10/19/10
to

hmm, I'd better reimplement it. It is in the manual, thus need to be
supported (contrary to some of the hooks I've added which aren't even
documented in the dtx).

Rasmus Villemoes

unread,
Oct 20, 2010, 8:18:16 AM10/20/10
to
Philipp Stephani <Look...@arcor.de> writes:

> Rasmus Villemoes <burner...@imf.au.dk> writes:
>
>> Is there an expl3 solution?
>
> None that I know, but here is a rather boring but robust solution that
> works only in pdfTeX:
>
> \def\ifnumeric#1\then{\ifnum\pdfmatch{^[0-9]+$}{#1}=1 }
> \let\then\iffalse
> \def\typeout{\immediate\write16}
> \typeout{\ifnumeric123\then yes\else no\fi}
> \typeout{\ifnumeric12x\then yes\else no\fi}
>

Thanks. I did think about using (\ifpdf and) a regexp test, since I
had heard about \pdfmatch some time ago. However, I couldn't find the
documentation for it anywhere. "texdoc pdftex" (in an updated TL2010)
gives a manual dated January 25, 2007, but a search for pdfmatch in
that file doesn't give anything. Is the exact syntax documented
anywhere? It would be nice to know which regex features one can
use. The solution above of course matches any non-negative integer
(with leading 0's allowed), but I actually need to allow only two and
four digit numbers.


BTW, if one searches CTAN for "pdfmatch" in the "Search the
documentation" field, one gets the rather odd result "There are 10
matching packages. Here are matches number 0-14."

Heiko Oberdiek

unread,
Oct 20, 2010, 8:44:04 AM10/20/10
to
Rasmus Villemoes <burner...@imf.au.dk> wrote:

> Philipp Stephani <Look...@arcor.de> writes:
>
> > Rasmus Villemoes <burner...@imf.au.dk> writes:
> >
> > \def\ifnumeric#1\then{\ifnum\pdfmatch{^[0-9]+$}{#1}=1 }
> > \let\then\iffalse
> > \def\typeout{\immediate\write16}
> > \typeout{\ifnumeric123\then yes\else no\fi}
> > \typeout{\ifnumeric12x\then yes\else no\fi}
> >
>
> Thanks. I did think about using (\ifpdf and) a regexp test, since I
> had heard about \pdfmatch some time ago.

Don't use \ifpdf for testing for \pdfmatch. \ifpdf checks for
pdfTeX in PDF mode. \pdfmatch is also available in DVI mode
and older pdfTeX versions have PDF mode, but some don't
know \pdfmatch.

Some ways for testing for \pdfmatch:

a)
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname pdfmatch\endcsname\relax
% not available
\else
% available
\fi

b)
\usepackage{ltxcmds}
\ltx@IfUndefined{pdfmatch}{%
% not available
}{%
% available
}

c) ...

> However, I couldn't find the
> documentation for it anywhere.

The supported regular expressions are called "POSIX 1003.2 regular
expressions", see manual page "man 7 regex".

> "texdoc pdftex" (in an updated TL2010)
> gives a manual dated January 25, 2007, but a search for pdfmatch in
> that file doesn't give anything. Is the exact syntax documented
> anywhere?

NEWS.

> It would be nice to know which regex features one can
> use. The solution above of course matches any non-negative integer
> (with leading 0's allowed), but I actually need to allow only two and
> four digit numbers.

There are many ways, e.g.:

\pdfmatch{^([0-9]{2}){1,2}$}{...}
\pdfmatch{^([0-9][0-9]|[0-9][0-9][0-9][0-9])$}{...}

Or with the restriction of the century:

\pdfmatch{^(19|20)?[0-9][0-9]$}{...}

usw.

> BTW, if one searches CTAN for "pdfmatch" in the "Search the
> documentation" field, one gets the rather odd result "There are 10
> matching packages. Here are matches number 0-14."

The following of my packages are using \pdfmatch
(the package version that uses \pdfmatch might not
be released yet):
* ltxcmds (matching version date strings of
\Provides(Class|Package|File)
* pdfrender
* askinclude
* attachfile2
* hycolor
* hyperref (mostly for checking option values)

--
Heiko Oberdiek

Message has been deleted

Dan Luecking

unread,
Oct 20, 2010, 2:50:58 PM10/20/10
to
On Tue, 19 Oct 2010 20:32:34 +0200, Heiko Oberdiek
<heiko.o...@googlemail.com> wrote:

>Rasmus Villemoes <burner...@imf.au.dk> wrote:
>
>> \newcommand{\checkifinteger}[1]{%
>> \protected@edef\@vsa{#1}%
>> \ifcat _\ifnum9<1\gobm{#1} _\else A\fi
>> \integertrue%
>> \else
>> \integerfalse%
>> \fi}
>> \newcommand{\gobm}[1]{#1}

...

>
>The use of \checkifinteger is rather limited:
>* Negative integers aren't detected as integers by this macro.
>* All that starts with one digit is taken as integer: 0.0, 4pt, 48foo

This last statement is not true. I analyse, for example
with 0.0,
\ifnum 9<10.0 _\else A\fi
This is true and produces ".0 _", resulting in
\ifcat_.0 _\integertrue\else\integerfalse\fi
This is false unless the normal category codes of "_" or "."
have been changed.

Indeed, I get false for each of those examples in a
document. Only digits followed by "_" mistakenly become
true, but an error is thrown by the second "_", even in math
mode.

Also \checkifinteger{1 } and \checkifinteger{ 1} are false.
This could be a feature or a bug depending on how it is used.

Heiko Oberdiek

unread,
Oct 20, 2010, 3:48:15 PM10/20/10
to
Dan Luecking <Look...@uark.edu> wrote:

> On Tue, 19 Oct 2010 20:32:34 +0200, Heiko Oberdiek
> <heiko.o...@googlemail.com> wrote:
>
> >Rasmus Villemoes <burner...@imf.au.dk> wrote:
> >
> >> \newcommand{\checkifinteger}[1]{%
> >> \protected@edef\@vsa{#1}%
> >> \ifcat _\ifnum9<1\gobm{#1} _\else A\fi
> >> \integertrue%
> >> \else
> >> \integerfalse%
> >> \fi}
> >> \newcommand{\gobm}[1]{#1}

> >* All that starts with one digit is taken as integer: 0.0, 4pt, 48foo


>
> This last statement is not true. I analyse, for example
> with 0.0,
> \ifnum 9<10.0 _\else A\fi
> This is true and produces ".0 _", resulting in
> \ifcat_.0 _\integertrue\else\integerfalse\fi
> This is false unless the normal category codes of "_" or "."
> have been changed.

Yes, you are right.

> Indeed, I get false for each of those examples in a
> document. Only digits followed by "_" mistakenly become
> true, but an error is thrown by the second "_", even in math
> mode.
>
> Also \checkifinteger{1 } and \checkifinteger{ 1} are false.
> This could be a feature or a bug depending on how it is used.

Yes, that's the main problem, the precise specification.
For example, \@cclv is mostly used as integer "255", but it isn't
expandable (defined by \chardef) and the test will result false.

--
Heiko Oberdiek

Heiko Oberdiek

unread,
Oct 20, 2010, 5:32:24 PM10/20/10
to
Dan Luecking <Look...@uark.edu> wrote:

> On Tue, 19 Oct 2010 20:32:34 +0200, Heiko Oberdiek
> <heiko.o...@googlemail.com> wrote:
>
> >Rasmus Villemoes <burner...@imf.au.dk> wrote:
> >
> >> \newcommand{\checkifinteger}[1]{%
> >> \protected@edef\@vsa{#1}%
> >> \ifcat _\ifnum9<1\gobm{#1} _\else A\fi
> >> \integertrue%
> >> \else
> >> \integerfalse%
> >> \fi}
> >> \newcommand{\gobm}[1]{#1}

> >* All that starts with one digit is taken as integer: 0.0, 4pt, 48foo


>
> This last statement is not true. I analyse, for example
> with 0.0,
> \ifnum 9<10.0 _\else A\fi
> This is true and produces ".0 _", resulting in
> \ifcat_.0 _\integertrue\else\integerfalse\fi
> This is false unless the normal category codes of "_" or "."
> have been changed.

Yes, you are right.

> Indeed, I get false for each of those examples in a
> document. Only digits followed by "_" mistakenly become
> true, but an error is thrown by the second "_", even in math
> mode.
>
> Also \checkifinteger{1 } and \checkifinteger{ 1} are false.
> This could be a feature or a bug depending on how it is used.

Yes, that's the main problem, the precise specification.


For example, \@cclv is mostly used as integer "255", but it

is not expandable (defined by \chardef) and the test will

Heiko Oberdiek

unread,
Oct 20, 2010, 3:50:26 PM10/20/10
to
Dan Luecking <Look...@uark.edu> wrote:

> On Tue, 19 Oct 2010 20:32:34 +0200, Heiko Oberdiek
> <heiko.o...@googlemail.com> wrote:
>
> >Rasmus Villemoes <burner...@imf.au.dk> wrote:
> >
> >> \newcommand{\checkifinteger}[1]{%
> >> \protected@edef\@vsa{#1}%
> >> \ifcat _\ifnum9<1\gobm{#1} _\else A\fi
> >> \integertrue%
> >> \else
> >> \integerfalse%
> >> \fi}
> >> \newcommand{\gobm}[1]{#1}

> >* All that starts with one digit is taken as integer: 0.0, 4pt, 48foo


>
> This last statement is not true. I analyse, for example
> with 0.0,
> \ifnum 9<10.0 _\else A\fi
> This is true and produces ".0 _", resulting in
> \ifcat_.0 _\integertrue\else\integerfalse\fi
> This is false unless the normal category codes of "_" or "."
> have been changed.

Yes, you are right.

> Indeed, I get false for each of those examples in a
> document. Only digits followed by "_" mistakenly become
> true, but an error is thrown by the second "_", even in math
> mode.
>
> Also \checkifinteger{1 } and \checkifinteger{ 1} are false.
> This could be a feature or a bug depending on how it is used.

Yes, that's the main problem, the precise specification.
For example, \@cclv is mostly used as integer "255", but it isn't

Heiko Oberdiek

unread,
Oct 21, 2010, 6:24:38 AM10/21/10
to
Dan Luecking <Look...@uark.edu> wrote:

> On Tue, 19 Oct 2010 20:32:34 +0200, Heiko Oberdiek
> <heiko.o...@googlemail.com> wrote:
>
> >Rasmus Villemoes <burner...@imf.au.dk> wrote:
> >
> >> \newcommand{\checkifinteger}[1]{%
> >> \protected@edef\@vsa{#1}%
> >> \ifcat _\ifnum9<1\gobm{#1} _\else A\fi
> >> \integertrue%
> >> \else
> >> \integerfalse%
> >> \fi}
> >> \newcommand{\gobm}[1]{#1}

> >* All that starts with one digit is taken as integer: 0.0, 4pt, 48foo


>
> This last statement is not true. I analyse, for example
> with 0.0,
> \ifnum 9<10.0 _\else A\fi
> This is true and produces ".0 _", resulting in
> \ifcat_.0 _\integertrue\else\integerfalse\fi
> This is false unless the normal category codes of "_" or "."
> have been changed.

Yes, you are right.

> Indeed, I get false for each of those examples in a
> document. Only digits followed by "_" mistakenly become
> true, but an error is thrown by the second "_", even in math
> mode.
>
> Also \checkifinteger{1 } and \checkifinteger{ 1} are false.
> This could be a feature or a bug depending on how it is used.

Yes, that's the main problem, the precise specification.


For example, \@cclv is mostly used as integer "255", but it

is not expandable (defined by \chardef) and the test will

GL

unread,
Oct 21, 2010, 6:31:15 AM10/21/10
to
Le 20/10/2010 14:44, Heiko Oberdiek a écrit :

> Rasmus Villemoes<burner...@imf.au.dk> wrote:
>
> Or with the restriction of the century:
>
> \pdfmatch{^(19|20)?[0-9][0-9]$}{...}

I thought your meant "a huge restriction" (of the century!) lol ;-)

My workaround without \pdfmatch:

\def\isanumber#1#2\relax\@nnil{% \relax is to mimick the syntax of
\@defaultunits
\afterassignment\isa@number#1\number0#2\relax\isa@number
}% \isanumber
\def\isa@number#1\relax#2\isa@number{%
\ifblank{#1}
{\isa@number@{}#2\isa@number@\@nnil
\csname ltx@\ifx\@let@token\isa@number@
first\else second\fi oftwo\endcsname}
\ltx@secondoftwo
}% \isa@number
\def\isa@number@#1{\futurelet\@let@token\isa@number@@}
\def\isa@number@@{%
\csname \ifx\@let@token\relax
isa@number@\else remove@to@nnil\fi
\endcsname
}% \isa@number@@

\loggingall
\isanumber\count@ 12\relax\@nnil
{Yes and the value is \the\count@}
{No and count@ has been left to its previous value}

\isanumber\count@ Hello\relax\@nnil
{Yes and the value is \the\count@}
{No and count@ has been left to its previous value}

% However, this doesn't work with \@ne \tw@ etc. because
% \count@ = \number 0\@ne assigns 0

\isanumber\count@ \tw@\relax\relax\relax \relax\@nnil
{Yes and the value is \the\count@}
{No and count@ has been left to its previous value}


There is also \ifstrnum in etextools.sty
etextools is not a `good package' I admit, but sometimes
it may give ideas when you are lost... and the doc is
inimitable isn't it ?


Regards

GL

unread,
Oct 21, 2010, 6:34:51 AM10/21/10
to
Le 21/10/2010 12:31, GL a écrit :
> Le 20/10/2010 14:44, Heiko Oberdiek a écrit :
>> Rasmus Villemoes<burner...@imf.au.dk> wrote:


> \isanumber\count@ Hello\relax\@nnil
> {Yes and the value is \the\count@}

{No and \string\count@\space is 0}% (sorry)
> %{No and count@ has been left to its previous value}

Donald Arseneau

unread,
Oct 21, 2010, 7:29:31 AM10/21/10
to
GL <goua...@gmail.com> writes:

> Le 20/10/2010 14:44, Heiko Oberdiek a écrit :
> > Rasmus Villemoes<burner...@imf.au.dk> wrote:
> >
> > Or with the restriction of the century:
> >
> > \pdfmatch{^(19|20)?[0-9][0-9]$}{...}
>
> I thought your meant "a huge restriction" (of the century!) lol ;-)

Consider this the hint of the century.

Oh no, I've said too much.

--
Donald Arseneau as...@triumf.ca

Ahmed Musa

unread,
Oct 28, 2010, 11:45:15 AM10/28/10
to
On Oct 21, 11:31 am, GL <gouail...@gmail.com> wrote:
> Le 20/10/2010 14:44, Heiko Oberdiek a écrit :
>
> > Rasmus Villemoes<burner+use...@imf.au.dk>  wrote:


The following solution removes the restrictions of GL's solution. In
order to ensure expandability, however, there is one caveat here: plus
(+) and minus (-) should not appear more than once in the expression.
I am keen to see this restrictions removed, although it seems more
appropriate to first do any complex arithmetic outside the test. Also
TeX's maximum dimension should not be exceeded.

\begingroup
\catcode`P=12
\catcode`T=12
\lowercase{%
\def\x{\endgroup
\def\@ifinteger##1.##2PT{%
\expandafter\ifx\expandafter\\\romannumeral0%
\ifnum##2>\z@\@afterfi\r@move@to@nnil\fi\@space
\\\remove@to@nnil\@nnil
}%
}%
}
\x
\def\@afterfi#1\fi{\fi#1}
\def\r@move@to@nnil#1\@nnil{\noexpand\@nnil}
\long\def\ifinteger#1\then{%
\expandafter\@ifinteger
\the\dimexpr\@mminus\@pplus#1\p@\remove@to@nnil+-\@nnil\relax
}
\let\then\iffalse
\def\@mminus#1-{#1\p@-}
\def\@pplus#1+{#1\p@+}

% Tests:
\edef\x{\ifinteger\count@+1\then Yes\else No\fi}
\edef\y{\ifinteger\count@-\@ne+\tw@\then Yes\else No\fi}
\edef\z{\ifinteger\count@-1.3+1.2\then Yes\else No\fi}

\edef\g{\the\dimexpr\count@ pt-1.1pt+1.2pt-1.3pt}
\edef\h{\expandafter\ifinteger\expandafter\rem@pt\g\then Yes\else No
\fi}

\edef\x{\the\dimexpr\count@ pt-1pt+2pt-3pt}
\edef\y{\expandafter\ifinteger\expandafter\rem@pt\x\then Yes\else No
\fi}

0 new messages