2012-02-02 5 views
10

आईएफ गलत जवाब देता है जब मैं 2 बड़ी संख्याओं की तुलना करने की कोशिश करता हूं।विंडोज बैच फ़ाइल IF विफलता - 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 दोनों पक्षों को संख्याओं के रूप में व्याख्या करेगा। यह आईएफ को सही तरीके से निर्धारित करने में सक्षम बनाता है कि 10 9 से अधिक है। यदि आपके पास कोई गैर-अंक वर्ण हैं, तो IF स्ट्रिंग तुलना करता है। उदाहरण के लिए, "10" "9" से कम है क्योंकि उद्धरण अंक नहीं हैं, और 9 से कम 1 प्रकार

प्रश्न में तुलना विफल होने का कारण यह है क्योंकि CMD.EXE 2147483647 से बड़ी संख्याओं को संसाधित नहीं कर सकता है। आईएफ में एक अजीब डिजाइन क्विर्क 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 

ध्यान दें कि रिक्तियों के साथ लगाकर छोड़ दिया शून्य के रूप में बस के रूप में अच्छी तरह से काम करता है।

आप बाद में अग्रणी शून्य जब भी आप निम्नलिखित का उपयोग कर करना चाहते हैं हटा सकते हैं (या प्रमुख रिक्त स्थान को दूर करने के लिए अनुकूलित)

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 टेराबाइट्स के बराबर है। मुझे लगता है कि इससे पहले कि हम उससे अधिक डिस्क ड्राइव से निपटने के लिए कुछ समय लगेगा। (किंतु कौन जानता है!)

संपादित - कैसे पार्स संख्या यदि जानबूझकर ज्यादा साधारण है की मेरे विवरण। अगर वास्तव में नकारात्मक संख्याओं, साथ ही हेक्स और ऑक्टल नोटेशन का समर्थन करता है। अधिक विस्तृत स्पष्टीकरण के लिए Rules for how CMD.EXE parses numbers देखें।

+0

यह वास्तव में बहुत अच्छा था। धन्यवाद – Lupocci

+0

संख्यात्मक तुलना की जाती है यदि दोनों पक्ष अच्छी तरह से गठित संख्याएं हैं - न केवल सख्ती से दशमलव अंक। उदाहरण के लिए -1 या 0xabc या +43 संख्यात्मक रूप से तुलना करेंगे, लेकिन 09 नहीं होगा (0 अमान्य ऑक्टल है)। –

+1

@ पॉल - बिल्कुल सही है, लेकिन मैं बड़ी संख्या से निपटने वाले क्यू एंड ए के केंद्रीय बिंदु से विचलित नहीं होना चाहता था। मैं एक संक्षिप्त स्पष्टीकरण के साथ आने के लिए संघर्ष कर रहा था जो बड़ी संख्या में अधिकतम पूर्णांक पूर्णांक के रूप में माना जा रहा है, इस बिंदु को खत्म नहीं करेगा। अधिक जानकारी [सीएमडी.एक्सईई पार्स संख्याओं के लिए नियम] पर उपलब्ध है [http://www.dostips.com/forum/viewtopic.php?t=3758) – dbenham