dbe*_*ham 12 if-statement batch-file
当我尝试比较2个大数字时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%
Run Code Online (Sandbox Code Playgroud)
产生
30000000000000 is equal to 40000000000
Run Code Online (Sandbox Code Playgroud)
发生了什么,我该如何解决这个问题?
dbe*_*ham 32
如果IF比较的两边都严格地由十进制数字组成,则IF将双方都解释为数字.这使IF能够正确地确定10大于9.如果您有任何非数字字符,则IF进行字符串比较.例如,"10"小于"9",因为引号不是数字,1分类低于9.
问题中的比较失败的原因是因为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%"
Run Code Online (Sandbox Code Playgroud)
生成正确的字符串比较结果
"30000000000000" is less than "40000000000"
Run Code Online (Sandbox Code Playgroud)
但在大多数情况下,这不是想要的.
如果您想进行数字比较,那么该过程会涉及更多.您需要将数字转换为一个字符串,该字符串将正确排序为数字.这是通过在数字字符串前面添加零来实现的,其方式是使两个数字字符串具有相同的宽度.最简单的解决方案是确定您需要支持的最大位数 - 例如,对于此示例,请说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
Run Code Online (Sandbox Code Playgroud)
生产 -
030000000000000 is greater than 000040000000000
Run Code Online (Sandbox Code Playgroud)
请注意,带有空格的左前缀与零一样有效.
您可以稍后在需要时使用以下内容删除前导零(或者适应删除前导空格)
for /f "tokens=* delims=0" %%A in ("%n1%") do set "n1=%%A"
if not defined n1 set "n1=0"
Run Code Online (Sandbox Code Playgroud)
通常我们不处理批处理文件中的大数字.但是,如果我们查看硬盘上的可用空间,它们很容易就会突然出现.太字节磁盘驱动器现在相对便宜.这是我第一次在/sf/answers/636967971/进行大数字比较
我选择在我的例子中支持15位数,因为这相当于近999太字节.我想在我们必须处理大于那个的磁盘驱动器之前还需要一段时间.(但谁知道!)
编辑 - 我对IF如何解析数字的描述故意过于简单化.IF实际上支持负数,以及十六进制和八进制表示法.有关 CMD.EXE如何解析数字的详细信息,请参阅规则.