If statement 使用IF会产生奇怪的结果
受和它的答案的启发,我做了一些测试。 一个答案是,数字太大(在32位整数中)会被截断,但这并不能解释结果。而且很明显,它不会将两边作为字符串进行比较(正如我所期望的那样)。似乎If statement 使用IF会产生奇怪的结果,if-statement,cmd,If Statement,Cmd,受和它的答案的启发,我做了一些测试。 一个答案是,数字太大(在32位整数中)会被截断,但这并不能解释结果。而且很明显,它不会将两边作为字符串进行比较(正如我所期望的那样)。似乎如果感到困惑并想“好吧,我不知道-给它一个真实的答案”。(使用neq,gtr,lss代替equ,geq,leq总是给出FALSE) 如果a和/或b中的任何一个在32位整数的边界内,或包含[0-9]中的任何字符,则代码按预期工作 @echo off set a=333333333333 set b=444444444444
如果
感到困惑并想“好吧,我不知道-给它一个真实的答案”。(使用neq
,gtr
,lss
代替equ
,geq
,leq
总是给出FALSE)
如果a
和/或b
中的任何一个在32位整数的边界内,或包含[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 -)
@echo关闭
设置a=333
组b=4444
呼叫:比较
组b=2222
呼叫:比较
后藤:eof
:比较
回显将%a%与%b%进行比较
如果%a%geq%b%(echo a^>=b)其他(echo-)
如果%b%geq%a%(echo b^>=a)其他(echo-)
如果%a%leq%b%(回声a^这是一个极限
C:>set /A a=333333333333
Invalid number. Numbers are limited to 32-bits of precision.
此结果的原因可以在函数文档中找到,该函数首先使用比较运算符eq
,NEQ
,LSS
,LEQ
,GTR
,GEQ
,如我在上的回答中所述
返回值
成功后,函数将转换后的整数作为长整型值返回。
如果无法执行有效转换,则返回零值(0L)。
如果读取的值超出可表示值的范围,则函数返回long_MAX或long_MIN(在中定义),并设置为ERANGE
最后一句话在这里最重要
如果cmd.exe
中的编码类似于此C代码,则看起来像是:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char* argv[])
{
const char csNo[] = "no";
const char csYes[] = "yes";
char* pcEndValue1;
char* pcEndValue2;
int iExitCode = 2;
int iErrorNumber1;
int iErrorNumber2;
int iStringResult1;
int iStringResult2;
long lIntegerValue1;
long lIntegerValue2;
if(argc > 2)
{
/* Convert the two arguments to 32-bit signed integers. */
lIntegerValue1 = strtol(argv[1],&pcEndValue1,0);
iErrorNumber1 = errno;
lIntegerValue2 = strtol(argv[2],&pcEndValue2,0);
iErrorNumber2 = errno;
/* Failed the conversion for any of the two arguments? */
if(((lIntegerValue1 == 0) && (*pcEndValue1 != '\0')) ||
((lIntegerValue2 == 0) && (*pcEndValue2 != '\0')))
{
/* Compare case-sensitive the two arguments as strings. */
iStringResult1 = strcmp(argv[1],argv[2]);
iStringResult2 = strcmp(argv[2],argv[1]);
printf("String comparing %s (a) with %s (b):\n\n",argv[1],argv[2]);
printf("a GEQ b: %s\n",(iStringResult1 >= 0) ? csYes : csNo);
printf("b GEQ a: %s\n",(iStringResult2 >= 0) ? csYes : csNo);
printf("a LEQ b: %s\n",(iStringResult1 <= 0) ? csYes : csNo);
printf("b LEQ a: %s\n",(iStringResult2 <= 0) ? csYes : csNo);
printf("a EQU b: %s\n",(iStringResult2 == 0) ? csYes : csNo);
iExitCode = 1;
}
else
{
/* Compare the values. */
printf("Value comparing %s/%ld (a) with %s/%ld (b):\n\n",argv[1],lIntegerValue1,argv[2],lIntegerValue2);
printf("a GEQ b: %s\n",(lIntegerValue1 >= lIntegerValue2) ? csYes : csNo);
printf("b GEQ a: %s\n",(lIntegerValue2 >= lIntegerValue1) ? csYes : csNo);
printf("a LEQ b: %s\n",(lIntegerValue1 <= lIntegerValue2) ? csYes : csNo);
printf("b LEQ a: %s\n",(lIntegerValue2 <= lIntegerValue1) ? csYes : csNo);
printf("a EQU b: %s\n",(lIntegerValue2 == lIntegerValue1) ? csYes : csNo);
iExitCode = 0;
}
printf("\nError number a: %d ... %s\n",iErrorNumber1,strerror(iErrorNumber1));
printf("Error number b: %d ... %s\n",iErrorNumber2,strerror(iErrorNumber2));
}
return iExitCode;
}
并且使用参数运行可执行文件3333333332222222
会导致例如输出:
Value comparing 333333333333/2147483647 (a) with 444444444444/2147483647 (b):
a GEQ b: yes
b GEQ a: yes
a LEQ b: yes
b LEQ a: yes
a EQU b: yes
Error number a: 2 ... Output of function out of range (ERANGE)
Error number b: 2 ... Output of function out of range (ERANGE)
Value comparing 333333333333/2147483647 (a) with 222222222222/2147483647 (b):
a GEQ b: yes
b GEQ a: yes
a LEQ b: yes
b LEQ a: yes
a EQU b: yes
Error number a: 2 ... Output of function out of range (ERANGE)
Error number b: 2 ... Output of function out of range (ERANGE)
注意:根据使用的C编译器标准库,错误号和相应的错误字符串可能会有所不同
在这两个测试用例中,两个参数在从字符串转换为长整数时都会导致32位有符号整数溢出。因此strtol
返回所有四个值long_MAX
,并将errno
设置为ERANGE
。但是溢出条件不会由cmd.exe中的IF代码评估e> 。它只是检查转换结果,以及两个参数的结束指针指向哪个字符,如上面的C代码所示
换句话说,IF处理比较运算符eq
,NEQ
,LSS
,LEQ
,GTR
,GEQ
的使用始终是一个整数比较,只要两个参数中的任何一个不会因为参数中的无效字符而从字符串到整数的转换失败字符串。如果不进行整数比较,则超出范围条件不是的理由
只有当两个参数字符串中的一个包含无效的整数字符时,才会进行字符串比较。是的,我完全了解32位整数及其限制。但我的问题不是关于set/A
,而是关于if
。当if
检测到“非-(INT32)时-数字,它不应该使用字符串比较吗?(是的,我知道,把两边都加上引号会强制进行字符串比较,但这不是我的问题)转换为大数字上的字符串比较可能是一件理想的事情。它似乎不是cmd
所做的。如果代码有可能有这么大的数字,为什么不引用它们并继续。您是否在考虑节省几微秒的时钟?如果是这样,应该选择另一种语言。cmd
将其作为字符串处理-如果不是,则会出现语法或溢出错误。此外,
上的echo显示,它是按原样解析的。它是if
本身,它无法处理它,并且总是使用eq
、geq
和leq
为真,而使用eq
、geq
和leq
为假。我想了解原因。我认为有可能cmd
没有将其作为字符串处理。如果将其作为数字处理,则超出范围。对两个超出范围的数字执行比较运算符可能没有意义。我本希望收到错误消息,但这会有所帮助。超出范围的数字应该是确定的y给出一个错误(已经在解析阶段了-甚至在给if
之前),所以我认为它肯定是一个字符串。您希望发生什么?链接回“这个问题”没有提供使这成为一个独立问题的上下文。我希望字符串比较或errormessage,但string1不等于、不小于或不大于string2(而且它显然不是数字(从某种意义上说,cmd
如何工作-这意味着不是32位INT)echo on
清楚地表明,没有发生截断或转换,因此这似乎不是cmd
解析问题,而是if
本身的问题。我想了解,发生了什么以及为什么。可能是重复的-这就是我一直在寻找的东西!“。所以我怀疑,if
的程序员有点懒。。。