2012-02-02 85 views
10

如果我尝试比较2个大数字,IF会给出错误的答案。Windows批处理文件如果失败 - 30000000000000如何等于40000000000?

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

@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 

这是怎么回事?我该如何解决这个问题?

回答

30

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

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

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

@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 

注意,留下了空间前缀效果一样好为零。

,只要你想使用以下以后,您可以删除前导零(或适应删除前导空格)

for /f "tokens=* delims=0" %%A in ("%n1%") do set "n1=%%A" 
if not defined n1 set "n1=0" 

通常我们不处理在批处理文件中大量涌现。但是如果我们查看硬盘上的可用空间,他们很容易出现问题。太字节磁盘驱动器现在相对便宜。这是我第一次碰到大数的比较https://stackoverflow.com/a/9099542/1012053

我选择在我的例子中支持15位数,因为这相当于几乎999千兆字节。我想这将是一段时间,然后才能处理比这更大的磁盘驱动器。 (但谁知道!)

编辑 - 我对IF如何解析数字的描述是故意过于简单化的。 IF实际上支持负数,以及十六进制和八进制符号。有关更详尽的解释,请参阅Rules for how CMD.EXE parses numbers

+0

这真的很棒。谢谢 – Lupocci 2016-10-26 12:11:52

+0

如果双方都是格式良好的数字 - 不仅仅是严格的十进制数字,数字比较就完成了。例如-1或0xabc或+43会比较数字,但09不会(09是无效的八进制)。 – 2017-05-24 06:22:51

+1

@PaulH - 绝对正确,但我不想分散处理大量问题的问题的中心点。我努力想出一个简洁的解释,它不会压倒大数字被视为最大允许整数的观点。更多信息可以在[CMD.EXE如何解析数字的规则]中找到(http://www.dostips.com/forum/viewtopic.php?t=3758) – dbenham 2017-05-24 13:12:36

相关问题