2012-02-02 37 views
10

NẾU đưa ra câu trả lời sai khi tôi cố gắng so sánh 2 số lớn.Tập tin batch của Windows NẾU thất bại - Làm thế nào có thể 30000000000000 bằng 40000000000?

Ví dụ, tập tin thực thi đơn giản này

@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% 

sản xuất

30000000000000 is equal to 40000000000 

gì đang xảy ra, và làm thế nào để sửa lỗi này?

Trả lời

30

Nếu cả hai bên của so sánh IF được tạo thành đúng các chữ số thập phân, thì IF sẽ giải thích cả hai bên là số. Đây là điều cho phép IF xác định chính xác rằng 10 lớn hơn 9. Nếu bạn có bất kỳ ký tự không phải chữ số nào, thì IF thực hiện so sánh chuỗi. Ví dụ: "10" nhỏ hơn "9" vì dấu ngoặc kép không phải là chữ số và 1 loại thấp hơn 9.

Lý do so sánh trong câu hỏi không thành công vì CMD.EXE không thể xử lý số lớn hơn 2147483647. Một quirk thiết kế lẻ trong IF xử lý bất kỳ số nào lớn hơn 2147483647 như bằng 2147483647.

Nếu bạn muốn so sánh chuỗi số lớn, thì giải pháp rất dễ dàng. Bạn chỉ cần thêm 1 hoặc nhiều ký tự không phải chữ số vào cả hai mặt của điều kiện. Các kịch bản sau đây -

@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%" 

tạo ra chuỗi so sánh chính xác kết quả

"30000000000000" is less than "40000000000" 

Nhưng trong nhiều trường hợp, đây không phải là những gì đang bị truy nã.

Nếu bạn muốn so sánh bằng số, thì quá trình này có liên quan nhiều hơn một chút. Bạn cần phải chuyển đổi số thành một chuỗi sẽ sắp xếp đúng như một số. Điều này được thực hiện bằng cách đặt trước chuỗi số bằng số không theo cách làm cho cả hai chuỗi số có cùng chiều rộng. Giải pháp đơn giản nhất là xác định số lượng chữ số tối đa bạn cần hỗ trợ - giả sử 15 cho ví dụ này. Vì vậy, bạn tiền tố mỗi giá trị với 15 số không, và sau đó chỉ giữ lại tối đa 15 ký tự bằng cách sử dụng một hoạt động chuỗi con. Bạn cũng cần phải thêm một chữ số không cho cả hai mặt như trước - một lần nữa báo giá hoạt động tốt.

kịch bản này -

@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 

sản xuất -

030000000000000 is greater than 000040000000000 

Lưu ý rằng trái tiền tố với các không gian hoạt động giống cũng như số không.

Bạn sau này có thể loại bỏ các số không hàng đầu bất cứ khi nào bạn muốn sử dụng sau đây (hoặc thích nghi để loại bỏ không gian hàng đầu)

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

Thông thường chúng ta không đối phó với số lượng lớn trong các tập tin batch. Nhưng họ có thể dễ dàng cắt lên nếu chúng ta nhìn vào không gian trống trên đĩa cứng. Các ổ đĩa Terabyte hiện nay tương đối rẻ. Đây là cách tôi lần đầu tiên chạy vào so sánh số lượng lớn tại https://stackoverflow.com/a/9099542/1012053

Tôi đã chọn hỗ trợ 15 chữ số trong ví dụ của mình vì số đó tương đương với gần 999 terabyte. Tôi tưởng tượng nó sẽ là một thời gian trước khi chúng ta phải đối phó với ổ đĩa lớn hơn. (Nhưng ai biết được!)

CHỈNH SỬA - Mô tả của tôi về cách phân tích cú pháp số là cố ý quá đơn giản. NẾU thực sự hỗ trợ các số âm, cũng như ký hiệu hex và bát phân. Xem Rules for how CMD.EXE parses numbers để được giải thích kỹ lưỡng hơn.

+0

này là thực sự tuyệt vời. nhờ – Lupocci

+0

so Numeric được thực hiện nếu cả hai bên là những con số cũng như hình thành - không chỉ là chữ số thập phân đúng. Ví dụ -1 hoặc 0xabc hoặc +43 sẽ so sánh số lượng, nhưng 09 sẽ không (09 là bát phân không hợp lệ). –

+1

@PaulH - Hoàn toàn chính xác, nhưng tôi không muốn phân tâm từ các điểm trung tâm của Q & A đối phó với số lượng lớn. Tôi đấu tranh với một lời giải thích ngắn gọn mà sẽ không áp đảo điểm về số lượng lớn được coi là số nguyên tối đa cho phép. Xem thêm thông tin có sẵn tại [Rules bao CMD.EXE phân tích số] (http://www.dostips.com/forum/viewtopic.php?t=3758) – dbenham

Các vấn đề liên quan