Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
If statement Windows批处理文件如果失败-30000000000如何等于40000000000?_If Statement_Batch File - Fatal编程技术网

If statement Windows批处理文件如果失败-30000000000如何等于40000000000?

If statement Windows批处理文件如果失败-30000000000如何等于40000000000?,if-statement,batch-file,If Statement,Batch File,当我尝试比较两个大数字时,IF给出了错误的答案 例如,这个简单的批处理文件 @echo off setlocal set n1=30000000000000 set n2=40000000000 if %n1% gtr %n2% echo %n1% is greater than %n2% if %n1% lss %n2% echo %n1% is less than %n2% if %n1% equ %n2% echo %n1% is equal to %n2% 产生 30000000000

当我尝试比较两个大数字时,IF给出了错误的答案

例如,这个简单的批处理文件

@echo off
setlocal
set n1=30000000000000
set n2=40000000000
if %n1% gtr %n2% echo %n1% is greater than %n2%
if %n1% lss %n2% echo %n1% is less than %n2%
if %n1% equ %n2% echo %n1% is equal to %n2%
产生

30000000000000 is equal to 40000000000

发生了什么,我该如何解决这个问题?

如果If比较的两边都严格由十进制数字组成,那么If将把两边都解释为数字。这使IF能够正确确定10大于9。如果您有任何非数字字符,那么If将进行字符串比较。例如,“10”小于“9”,因为引号不是数字,而1排序低于9

问题中的比较失败的原因是CMD.EXE无法处理大于2147483647的数字。IF中的奇数设计怪癖将大于2147483647的任何数字视为等于2147483647

如果您想对大量的数字进行字符串比较,那么解决方案很简单。您只需要在条件的两侧添加1个或多个非数字字符。下面的脚本-

@echo off
setlocal
set n1=30000000000000
set n2=40000000000
if "%n1%" gtr "%n2%" echo "%n1%" is greater than "%n2%"
if "%n1%" lss "%n2%" echo "%n1%" is less than "%n2%"
if "%n1%" equ "%n2%" echo "%n1%" is equal to "%n2%"
生成正确的字符串比较结果

"30000000000000" is less than "40000000000"
但在大多数情况下,这并不是人们想要的

如果你想做一个数字比较,那么这个过程就要复杂一些。您需要将数字转换为一个字符串,该字符串将作为数字正确排序。这是通过在数字字符串前面加上零来实现的,使两个数字字符串的宽度相同。最简单的解决方案是确定您需要支持的最大位数——本例中假设为15位。因此,在每个值前面加上15个零,然后使用子字符串操作仅保留最右边的15个字符。您还需要像以前一样在两侧添加一个非数字-同样,引号也很有效

这个剧本-

@echo off
setlocal
set n1=30000000000000
set n2=40000000000
call :padNum n1
call :padNum n2
if "%n1%" gtr "%n2%" echo %n1% is greater than %n2%
if "%n1%" lss "%n2%" echo %n1% is less than %n2%
if "%n1%" equ "%n2%" echo %n1% is equal to %n2%
exit /b

:padNum
setlocal enableDelayedExpansion
set "n=000000000000000!%~1!"
set "n=!n:~-15!"
endlocal & set "%~1=%n%"
exit /b
产生-

030000000000000 is greater than 000040000000000
请注意,左前缀加空格的效果和零一样好

以后,您可以随时使用以下命令删除前导零(或调整以删除前导空格)

通常我们不会在批处理文件中处理大量数据。但如果我们查看硬盘上的可用空间,它们很容易出现。TB级磁盘驱动器现在相对便宜。这就是我第一次遇到大数字比较的原因

在我的示例中,我选择支持15位数字,因为这几乎等于999 TB。我想我们需要一段时间才能处理比这更大的磁盘驱动器。(但谁知道呢!)


编辑-我对IF如何解析数字的描述故意过于简单化。IF实际上支持负数,以及十六进制和八进制表示法。有关更详细的解释,请参阅。

如果两边都是格式良好的数字,而不仅仅是严格意义上的十进制数字,则会进行数字比较。例如,-1或0xabc或+43将在数字上进行比较,但09不会(09是无效的八进制)。@PaulH-绝对正确,但我不想偏离问答中处理大量数字的中心点。我很难想出一个简洁的解释,但这个解释不能压倒大数被视为最大允许整数的观点。有关更多信息,请访问@dbenham。我并不想吹毛求疵,但我最近被“严格的十进制数字”咬了一口——有前导的零,并期望进行数字比较。我一直不喜欢通过多位数数字的前导零来支持八进制(无论是C、CMD还是任何语言)。我想摆脱传统的表述是很困难的。
for /f "tokens=* delims=0" %%A in ("%n1%") do set "n1=%%A"
if not defined n1 set "n1=0"