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

How to test whether a variable is a positive, decimal integer?

561 views
Skip to first unread message

Timo Salmi

unread,
Jun 20, 2005, 4:21:21 PM6/20/05
to
DRAFT
106) How to test whether a variable is a positive, decimal integer?

This is one of the items which arose from a solution I needed
myself.
@echo off & setlocal enableextensions enabledelayedexpansion
if [%1]==[] (
echo Usage: %~f0 Parameter
goto :EOF)
::
:: Get the parameter into a variable
set s=%~1
::
:: Get its length, counting from zero
set charCount=0
for /l %%c in (0,1,255) do (
set si=!s:~%%c,1!
if defined si set /a charCount+=1)
set /a charCount=%charCount%-1
::
:: Test that only valid characters are present
set isInteger=true
for /l %%c in (0,1,%charCount%) do (
set si=!s:~%%c,1!
echo 1234567890|findstr /l "!si!">nul
if !errorlevel! GTR 0 set isInteger=false
)
::
:: Show the result
echo %s%
echo isInteger=%isInteger%
::
endlocal & goto :EOF
Examples of output
C:\_D\TEST>cmdfaq 1234
1234
isInteger=true
or
C:\_D\TEST>cmdfaq FF
FF
isInteger=false

The solution can be expanded to other numeric or alphabetic validity
tests. For example to test if a variable is a positive decimal
number.
@echo off & setlocal enableextensions enabledelayedexpansion
if [%1]==[] (
echo Usage: %~f0 Parameter
goto :EOF)
::
:: Get the parameter into a variable
set s=%~1
::
:: Get its length, counting from zero
set charCount=0
for /l %%c in (0,1,255) do (
set si=!s:~%%c,1!
if defined si set /a charCount+=1)
set /a charCount=%charCount%-1
::
:: Test that only valid characters are present
set isNumeric=true
set pointCount=0
for /l %%c in (0,1,%charCount%) do (
set si=!s:~%%c,1!
echo 1234567890.|findstr /l "!si!">nul
if !errorlevel! GTR 0 set isNumeric=false
if [!si!]==[.] set /a pointCount+=1
)
if %pointCount% GTR 1 set isNumeric=false
::
:: Show the result
echo %s%
echo isNumeric=%isNumeric%
::
endlocal & goto :EOF
The output could be e.g.
C:\_D\TEST>cmdfaq 12.34
12.34
isNumeric=true
or
C:\_D\TEST>cmdfaq 1..
1..
isNumeric=false

Phil Robyn

unread,
Jun 20, 2005, 5:03:30 PM6/20/05
to

Hi, Timo:

How about this?

==========begin file C:\cmd\test\isdecimal.cmd ==========
001. @echo off
002. setlocal
003. echo %~1|findstr /r "[^0-9.]">nul
004. if %errorlevel% equ 0 (
005. echo/contains non-numeric characters
006. goto :EOF
007. )
008. echo %~1|findstr "\.">nul
009. if %errorlevel% gtr 0 (
010. echo/it's numeric but not decimal
011. goto :EOF
012. )
013. set s1=%~1
014. set s2=%s1:*.=%
015. if not defined s2 goto :OK
016. echo %s2%|findstr "\.">nul
017. if %errorlevel% equ 0 (
018. echo/not a valid decimal number - contains more than one '.'
019. goto :EOF
020. )
021. :OK
022. echo/Looks like a valid positive decimal number
==========end file C:\cmd\test\isdecimal.cmd ==========

--
Phil Robyn
University of California, Berkeley

William Allen

unread,
Jun 20, 2005, 7:03:46 PM6/20/05
to
"Timo Salmi" wrote in message

> DRAFT
> 106) How to test whether a variable is a positive, decimal integer?
...snip

Wouldn't it be simpler merely to test the truth of:

IF 00%var% EQU 0%var%

since if VAR is a positive decimal integer, a numeric comparison is
performed (and the numbers are equal), otherwise a string comparison
is performed (and the strings are unequal).

Putting it in a Batch file called with the value to test as parameter 1:

Lines that don't begin with two spaces have wrapped accidentally
====Begin cut-and-paste (omit this line)
@ECHO OFF
IF [%1]==[] ECHO. Usage: %0 NumberToCheck&GOTO :EOF
IF 00%1 EQU 0%1 (ECHO/[%1] +ve integer) ELSE (ECHO/[%1] not +ve integer)

====End cut-and-paste (omit this line)
Simulated Win2000 for study/demo use. Cut-and-paste as Batch text file.
Batch file troubleshooting: http://www.allenware.com/find?UsualSuspects

--
William Allen
Free interactive Batch Course http://www.allenware.com/icsw/icswidx.htm
Batch Reference with examples http://www.allenware.com/icsw/icswref.htm
Header email is rarely checked. Contact us at http://www.allenware.com/


billious

unread,
Jun 20, 2005, 7:58:19 PM6/20/05
to

"William Allen" <_w...@email.com> wrote in message
news:42b74b75$0$2431$ed26...@ptn-nntp-reader02.plus.net...

Not quite William.
This will fail when the parameter supplied contains 8 or 9 because of the
peculiar decision to interpret leading-0 strings as octal.

[01]@echo off
[02]set ypi=%1
[03]:: strip leading zeroes
[04]:lzstrip
[05]if not defined ypi set ypi=0&goto stripped
[06]if %ypi:~0,1%==0 set ypi=%ypi:~1%&goto lzstrip
[07]:stripped
[08]set /a ypa=%ypi% >nul 2>nul
[09]if "%ypi%"=="%ypa%" (echo %1 positive integer) else (echo %1 not
positive integer)
[10]for %%i in (ypi ypa) do set %%i=

(I hope I don't need the standard blah-blah here)

Noting that changing 05 to
[05]if not defined ypi set ypi=x&goto stripped

will fulfill the strict definition (0 is not a positive integer)

...only tried as a quickie on XP/H before leaving to do stuff....

HTH

...Bill

Timo Salmi

unread,
Jun 21, 2005, 12:53:11 AM6/21/05
to
Phil Robyn <pro...@berkeley.edu> wrote:
> Timo Salmi wrote:
> > DRAFT
> > 106) How to test whether a variable is a positive, decimal integer?

> How about this?


> ==========begin file C:\cmd\test\isdecimal.cmd ==========

Very nice. Google reference to your posting included into the item.

All the best, Timo

--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FIN-65101, Finland
Useful script files and tricks ftp://garbo.uwasa.fi/pc/link/tscmd.zip

William Allen

unread,
Jun 21, 2005, 3:34:33 AM6/21/05
to
"billious" wrote in message
>
> "William Allen" wrote in message

...snip
> > Wouldn't it be simpler merely to test the truth of:
> >
> > IF 00%var% EQU 0%var%
...snip

> Not quite William.
> This will fail when the parameter supplied contains 8 or 9 because of the
> peculiar decision to interpret leading-0 strings as octal.

Noted. Thanks.

William Allen

unread,
Jun 21, 2005, 4:15:22 AM6/21/05
to
"William Allen" wrote in message
> "billious" wrote in message
> >
> > "William Allen" wrote in message
> ...snip
> > > Wouldn't it be simpler merely to test the truth of:
> > >
> > > IF 00%var% EQU 0%var%
> ...snip
> > Not quite William.
> > This will fail when the parameter supplied contains 8 or 9 because of the
> > peculiar decision to interpret leading-0 strings as octal.
>
> Noted. Thanks.

Keeping to the same general idea, since the IF command seems
happy with a leading + sign, this variant seems to be a workaround:

Lines that don't begin with two spaces have wrapped accidentally
====Begin cut-and-paste (omit this line)
@ECHO OFF
IF [%1]==[] ECHO. Usage: %0 NumberToCheck&GOTO :EOF

IF %1 EQU +%1 (ECHO/[%1] +ve integer) ELSE (ECHO/[%1] not +ve integer)

====End cut-and-paste (omit this line)
Simulated Win2000 for study/demo use. Cut-and-paste as Batch text file.
Batch file troubleshooting: http://www.allenware.com/find?UsualSuspects

--

William Allen

unread,
Jun 21, 2005, 4:46:23 AM6/21/05
to
"billious" wrote in message
...snip

> Not quite William.
> This will fail when the parameter supplied contains 8 or 9 because of the
> peculiar decision to interpret leading-0 strings as octal.

Incidentally, far from "peculiar", the treatment of lead-zero strings
as Octal is useful (and it follows SET /a guidelines). It means my
original idea can be used to test valid positive Octal integers, and
the following could be used to test for valid positive hexadecimal integers.

Lines that don't begin with two spaces have wrapped accidentally
====Begin cut-and-paste (omit this line)
@ECHO OFF
IF [%1]==[] ECHO. Usage: %0 NumberToCheck&GOTO :EOF

IF 0x%1 EQU 0x0%1 (ECHO/[%1] +ve hex integer) ELSE (ECHO/[%1] not +ve hex integer)

Dr John Stockton

unread,
Jun 21, 2005, 9:47:13 AM6/21/05
to
JRS: In article <d978g1$3os$1...@haavi.uwasa.fi>, dated Mon, 20 Jun 2005
20:21:21, seen in news:alt.msdos.batch.nt, Timo Salmi
<t...@poiju.uwasa.fi.uwasa.fi> posted :

>DRAFT
>106) How to test whether a variable is a positive, decimal integer?


But 0 is not positive, and may be allowable, and both 200.0 and 2e2 use
decimal notation and have positive integer values, except when 2e2 is
Hex.

This may be a case for developing a solution and then adjusting the
question with some care to fit!


The first point concerns the representation of variables.

An environment variable is a string, AFAIK; it cannot really be a
number, but it can represent a positive integer decimally. The test
should be on whether it is not empty, consists only of the characters
0-9, and maybe whether the first character is in 1-9. There are
variants for other bases, not necessarily needed or testable similarly.

Where a variable is held in a non-string format as a true Number, then
the test should be on the sign of the number and on its lacking a
fractional component; and there's probably no need to test the base.


If available, a Regular Expression test should be best for string
representations; see relevant examples in javascript <URL:http://www.mer
lyn.demon.co.uk/js-valid.htm>.

It looks as if Phil Robyn's solution uses RegExps, but maybe not with
the full power available in javascript.

When testing for non-integer numbers such as "123.456", one needs to
consider whether such as "123." or ".456" are allowed. They are
deprecated by, for example, IUPAP/SUNAMCO; they are unsafe, particularly
the latter, as a decimal point is such a small thing. One also needs to
consider whether to allow "123", or to require for that value "123.0".

OK = /^\d+$/.test(variable) // unsigned integer
OK = /^\d+(\.\d+)?$/.test(variable) // unsigned fixed-point

N.B. ISTM that Phil uses "decimal" to mean "has a dot". Outside the
USA, at least, "decimal" means "base 10" - and a decimal point is not
always a dot.


"How to test whether a variable holds a string of decimal digits" ???

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
<URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
<URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.

Timo Salmi

unread,
Jun 21, 2005, 5:41:06 PM6/21/05
to
Dr John Stockton <repl...@merlyn.demon.co.uk> wrote:
Timo Salmi <t...@poiju.uwasa.fi.uwasa.fi> posted :

> >106) How to test whether a variable is a positive, decimal integer?

> But 0 is not positive, and may be allowable,

Thanks. Right! Non-negative.

(While we are at it, John. Thanks for the comments you sent me a few
weeks ago. I would have liked to thank you privately, but FYI your
address in your email kept bouncing.)

> and both 200.0 and 2e2 use
> decimal notation and have positive integer values, except when 2e2 is
> Hex.

True, but batch tasks seldom are of the exponential type.
Non-negative integers are most likely. Anyway, after the basics are
presented, the detailed customization (as usual) is best done by the
user.

> USA, at least, "decimal" means "base 10" - and a decimal point is not
> always a dot.

In fact the appliaction I needed it for indeed rather is of the type
7
14
11:15

and the code I use there is

:: Test for the time parameter validity


:: Get the parameter into a variable
set s=%~1
::
:: Get its length

set charCount=0
set pointCount=0


for /l %%c in (0,1,255) do (
set si=!s:~%%c,1!
if defined si set /a charCount+=1

if [!si!]==[:] set /a pointCount+=1
)


::
:: Test that only valid characters are present
set isNumeric=true

echo %s%|findstr "[^0-9:]">nul
if %errorlevel% EQU 0 set isNumeric=false
::
:: Test for the right composition


if %pointCount% GTR 1 set isNumeric=false

if %charCount% EQU 3 set isNumeric=false
if %charCount% EQU 4 set isNumeric=false
if %charCount% GTR 5 set isNumeric=false
::
:: Was the time format correct
if [%isNumeric%]==[false] (
echo.
echo Error in the time parameter %s%
goto _usage
)

billious

unread,
Jun 21, 2005, 8:12:55 PM6/21/05
to

"William Allen" <_w...@email.com> wrote in message
news:42b7d404$0$3118$ed26...@ptn-nntp-reader01.plus.net...

> "billious" wrote in message
> ...snip
>> Not quite William.
>> This will fail when the parameter supplied contains 8 or 9 because of the
>> peculiar decision to interpret leading-0 strings as octal.
>
> Incidentally, far from "peculiar", the treatment of lead-zero strings
> as Octal is useful (and it follows SET /a guidelines). It means my
> original idea can be used to test valid positive Octal integers, and
> the following could be used to test for valid positive hexadecimal
> integers.
>

Hmmm...a matter of definition - and I don't think we need a war about it.

The fact that it's "useful" and follows the original NT set/a syntax is
justification after the fact. Cynics might consider that the fact that it's
consistent and follows the documentation is in itself "peculiar."

The very fact that the NT set/a syntax considered a numeric string decimal,
unless the initial character is zero when it became octal is peculiar - in
the sense of strange rather than unique. Given that the programmer
specifically introduced "0x" as a prefix for 'hex,' I'd have expected "0o"
for octal - particularly given the rarity of dealing with octal numbers
outside of Unix/PDP systems. But like so many other strangenesses with batch
(like inconsistent setting of ERRORLEVEL for instance) it's something we
just have to live with and hope that the next version doesn't change
establish methodologies. Far from being useful, it's a pain when calculating
on fragments of time and date - again the application of octal being
arguable - but not now please, I don't have the time (or interest if the
truth be known.)

We then get to the interpretation of "integer." Is +1234 an integer, or a
string whose value can be represented as an integer? How about 1234.0 or
1234. or 2e2?

Personally, I'll just make the arbitrary decision that in this case,
"integer" - or as the original proposition was framed, "positive, decimal
integer" means 'a string containing only characters from the set [0..9] with
the arguable exception or inclusion of a string consisting solely of the
character "0" .' All other hair-splitting is way beneath batchies in the
abysmal realm of lawyers.

...Bill


Dr John Stockton

unread,
Jun 22, 2005, 9:19:38 AM6/22/05
to
JRS: In article <d9a1hi$5pe$1...@haavi.uwasa.fi>, dated Tue, 21 Jun 2005
21:41:06, seen in news:alt.msdos.batch.nt, Timo Salmi
<t...@poiju.uwasa.fi.uwasa.fi> posted :

>Dr John Stockton <repl...@merlyn.demon.co.uk> wrote:
>Timo Salmi <t...@poiju.uwasa.fi.uwasa.fi> posted :
>> >106) How to test whether a variable is a positive, decimal integer?
>
>> But 0 is not positive, and may be allowable,
>
>Thanks. Right! Non-negative.
>
>(While we are at it, John. Thanks for the comments you sent me a few
>weeks ago. I would have liked to thank you privately, but FYI your
>address in your email kept bouncing.)

Sorry about that; one did indeed go to you with an address which is now
turned off due to spam. The reply address of this will work until mid-
July. But there's no hope for jrs@merlyn.

>In fact the appliaction I needed it for indeed rather is of the type

>11:15


>
>and the code I use there is
>
>:: Test for the time parameter validity

> ...

If a compact method can be found for processing the string with a RegExp
and returning an answer, then it should be better than that, not least
because the same harness could be used with any RegExp, and RegExps can
do such a lot.

I don't know whether FINDSTR accepts full RegExps, and cannot test it;
but, if it can, it would be best for NT/XP.


This test shows that MiniTrue, which Garbo has, and which can run in
DOS-16, DOS-32, and UNIX, can be driven by variables, returning what
matches the RegExp :

set RE=\d\d:\d\d
set ST=11:15
echo %ST% | mtr -x+ -o - %RE%
11:15

The result can in DOS..Win98/ME be sent to a variable with my STOW, and
in NT/XP by a standard technique. Caveat - MiniTrue needs care for end-
of-line matches; use echo%ST%!!! and append !!! to the RegExp. MiniTrue
could be made to output, or not, "set OK=1" for redirection and
execution.

echo %ST% | mtr -x+ -o - %RE% = "set OK=1"

MiniTrue HELP does not mention ErrorLevel; but my tests show that it
returns 0 for a successful search and 1 for failure; use the -n option.

echo %ST% | mtr -x+ -n - %RE%

Aha! see "Return Value" in its Help.


ISTM that SED should be able to do the test.

Javascript can do the RegExp test, can be run in WSH by CSCRIPT command,
and can read variables; I don't know whether it can write variables, but
the standard output can be captured as above. The javascript could be
fixed code (i.e. users copy from FAQ), returning for clarity false or
true, or 0 or 1 -- or even no/yes in Finnish, to use strings unlikely to
be already in use by non-Finns.

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk DOS 3.3, 6.20; Win98. ©
Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links.
PAS EXE TXT ZIP via <URL:http://www.merlyn.demon.co.uk/programs/00index.htm>
My DOS <URL:http://www.merlyn.demon.co.uk/batfiles.htm> - also batprogs.htm.

0 new messages