2012-02-02 83 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

相關問題