Inspired by this question and it's answers, I did some testing.
One answer suggests, the numbers are too big (out of 32bit integer) and they get truncated, but this doesn't explain the results. Also obviously it doesn't compare both sides as strings (as I would have expected). It seems that if
gets confused and thinks "well, I don't know - give it a TRUE". (Using neq
, gtr
, lss
instead of equ
, geq
, leq
always give FALSE).
The code works as expected, if any of a
and/or b
are within the borders of 32bit integer or contain any char out of [0-9].
@echo off
set a=333333333333
set b=444444444444
call :compare
set b=222222222222
call :compare
goto :eof
:compare
echo comparing %a% with %b%
if %a% geq %b% (echo a ^>= b) else (echo -)
if %b% geq %a% (echo b ^>= a) else (echo -)
if %a% leq %b% (echo a ^<= b) else (echo -)
if %b% leq %a% (echo b ^<= a) else (echo -)
if %a% equ %b% (echo a = b) else (echo -)
if %a% == %b% (echo a == b) else (echo -)
Is there any logical explanation for this, or is it just something we have to live with without thinking?
It is a limit.
The reason for this result can be found in documentation of function strtol which is used first on using the comparison operators
EQU
,NEQ
,LSS
,LEQ
,GTR
,GEQ
as explained in my answer on Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files.The last sentence is most important here.
It looks like IF in
cmd.exe
is coded similar to this C code:Compiling this C code as console application and running the executable with the parameters
333333333333 444444444444
results for example in output:And running the executable with the parameters
333333333333 222222222222
results for example in output:Note: The error number and the corresponding error string can differ depending on used C compiler respectively standard library.
In both test cases both arguments resulted in a 32-bit signed integer overflow on conversion from string to long int. Therefore
strtol
returned for all four valuesLONG_MAX
and seterrno
toERANGE
. But the overflow condition is not evaluated by code of IF incmd.exe
. It is just checked the conversion result and on which character the end pointer points to for both arguments like by the C code above.In other words IF processes on usage of comparison operators
EQU
,NEQ
,LSS
,LEQ
,GTR
,GEQ
always an integer comparison as long as conversion from string to integer does not fail for any of the two arguments because of an invalid character in argument strings. An out of range condition is no reason for IF not doing an integer comparison.A string comparison is done only if one of the two argument strings contains an invalid character for an integer.