74} How can I compare two numbers that have decimals with IF?
A straight comparison of two decimal numbers will not work reliably,
since they are interpreted and compared as strings because the
decimal point makes the number in fact a string. Consider the
following code, which will
not produce
wanted results.
@echo off & setlocal enableextensions
set number1=7.2
set number2=-7.3
::
:: Give the result
if %number1% EQU %number2% (
echo %number1% is equal to %number2%
) else (
if %number1% GTR %number2% (
echo %number1% is greater than %number2%
) else (
echo %number1% is smaller than %number2%
)
)
endlocal & goto :EOF
The output will, undesirably be
D:\TEST>cmdfaq
7.2 is smaller than -7.3
Instead, the following script will first convert the decimals into
integers for the comparison
@echo off & setlocal enableextensions
::
:: Get the numbers, one way or another
if not [%2]==[] (
set number1=%1
set number2=%2
) else (
echo Usage: %~f0 number1 number2
endlocal & goto :EOF
)
::
:: See to it that the numbers have at least four decimal places
call :Add4Decimals %number1% numb1
call :Add4Decimals %number2% numb2
::
:: Get the integer part and _exactly_ four decimals of the numbers
call :ParseNumber %numb1% fix1 dec1
call :ParseNumber %numb2% fix2 dec2
::
:: Build up the numbers to be compared
set /a n1=%fix1%%dec1%
set /a n2=%fix2%%dec2%
echo "Debugging" information: Comparing in fact
echo %fix1%%dec1% and %fix2%%dec2%
::
:: Give the result
if %n1% EQU %n2% (
echo %number1% is equal to %number2%
) else (
if %n1% GTR %n2% (
echo %number1% is greater than %number2%
) else (
echo %number1% is smaller than %number2%
)
)
endlocal & goto :EOF
::
:: =============================================
:Add4Decimals
setlocal enableextensions enabledelayedexpansion
echo %1|find ".">nul
if %errorlevel% EQU 1 (
endlocal& set %2=%1.0000&goto :EOF
) else (
endlocal& set %2=%10000&goto :EOF)
::
:: =============================================
:ParseNumber
setlocal enableextensions enabledelayedexpansion
for /f "tokens=1,2 delims=." %%m in ('echo %1') do (
set fix=%%m
set dec=%%n)
set dec=%dec:~0,4%
endlocal& set %2=%fix%& set %3=%dec%& goto :EOF
The output will be
D:\TEST>cmdfaq 7.2 -7.3
"Debugging" information: Comparing in fact
72000 and -73000
7.2 is greater than -7.3
A Visual Basic Script (VBScript) aided command line script solution:
@echo off & setlocal enableextensions
::
:: Get the numbers, one way or another
set number1=7.2
set number2=-7.3
::
:: Build a Visual Basic Script
if not exist c:\mytemp mkdir "c:\mytemp"
findstr "'%skip%VBS" "%~f0" > "c:\mytemp\tmp$$$.vbs"
::
:: Run the VBS script with Microsoft Windows Script Host Version 5.6
cscript //nologo "c:\mytemp\tmp$$$.vbs">"c:\mytemp\tmp$$$.cmd"
::
:: Call the CMD.EXE script created by the above redirection
call "c:\mytemp\tmp$$$.cmd"
::
:: Show and interpret the results
echo Testing: %number1% %number2% %sign%
if %sign% EQU 0 (
echo %number1% is equal to %number2%
) else (
if %sign% EQU 1 (
echo %number1% is greater than %number2%
) else (
echo %number1% is smaller than %number2%
)
)
::
:: Clean up
for %%f in ("c:\mytemp\tmp$$$.vbs" "c:\mytemp\tmp$$$.cmd") do (
if exist %%f del %%f)
rmdir "c:\mytemp"
endlocal & goto :EOF
'
'................................................................
'The Visual Basic Script
'
Set WshShell = WScript.CreateObject("WScript.shell") 'VBS
n1=WshShell.ExpandEnvironmentStrings("%number1%") 'VBS
n2=WshShell.ExpandEnvironmentStrings("%number2%") 'VBS
WScript.StdOut.WriteLine "@set sign=" & Sgn(n1-n2) 'VBS
The output will be
D:\TEST>cmdfaq
Testing: 7.2 -7.3 1
7.2 is greater than -7.3
A G(nu)AWK aided solution
@echo off & setlocal enableextensions
::
:: Get the numbers, one way or another
set number1=7.2
set number2=-7.3
::
:: Build a GnuAWK program file
if not exist c:\mytemp mkdir c:\mytemp
> c:\mytemp\tmp$$$.awk echo BEGIN{
>>c:\mytemp\tmp$$$.awk echo if ^(^(%number1%^)-^(%number2%^)==0^) sgn=0
>>c:\mytemp\tmp$$$.awk echo else if ^(index^(^(%number1%^)-^(%number2%^),"-"^)^) sgn=-1
>>c:\mytemp\tmp$$$.awk echo else sgn=1
>>c:\mytemp\tmp$$$.awk echo printf "@set sign=%%s\n",sgn
>>c:\mytemp\tmp$$$.awk echo }
::
:: Execute
gawk -f c:\mytemp\tmp$$$.awk>c:\mytemp\tmp$$$.cmd
call c:\mytemp\tmp$$$.cmd
::
:: Show and interpret the results
echo Testing: %number1% %number2% %sign%
if %sign% EQU 0 (
echo %number1% is equal to %number2%
) else (
if %sign% EQU 1 (
echo %number1% is greater than %number2%
) else (
echo %number1% is smaller than %number2%
)
)
::
:: Clean up
for %%f in (c:\mytemp\tmp$$$.awk c:\mytemp\tmp$$$.cmd) do del %%f
rmdir c:\mytemp
endlocal & goto :EOF
The output will again be
D:\TEST>cmdfaq
Testing: 7.2 -7.3 1
7.2 is greater than -7.3