88} How to convert DEC to HEX with a script file, and vice versa? (revisited)
If you want a pure script only solution, see items
32
and
33
in this FAQ. If you want to convert a string given in hexadecimals see
item
73.
For a command-line calculator type of a solution for Dec to Hex (etc) see
item
61.
This can be also done e.g. with
G(nu)AWK
or a
Visual Basic Script (VBScript). The
gawk solutions are given below. No error checking for the correct
input format of the digits is included in the conversion algorithms.
To put the results in an environment variable see the DEC to BIN awk
and VBScript examples in this item.
@echo off & setlocal enableextensions disabledelayedexpansion
rem DEC to HEX
::
:: Usage
if "%~1"=="" (
echo.
echo Usage: %~f0 [DecimalNumber] to be converted to Hexadecimal
goto :EOF)
::
:: Build an awk source
set awksrc="%temp%\tmp$$$.awk"
> %awksrc% echo BEGIN{
>> %awksrc% echo number=%1
>> %awksrc% echo base=16
>> %awksrc% echo digit="0123456789ABCDEF"
>> %awksrc% echo result=""
>> %awksrc% echo while(number
!=0)
>> %awksrc% echo {
>> %awksrc% echo i=number-base*int(number/base)
>> %awksrc% echo result=substr(digit,i+1,1)result
>> %awksrc% echo number=int(number/base)
>> %awksrc% echo }
>> %awksrc% echo printf"%%s\n",result
>> %awksrc% echo }
::
:: Run the awk source
gawk -f %awksrc%
::
:: Clean up
for %%f in (%awksrc%) do if exist %%f del %%f
endlocal & goto :EOF
An example of the output
C:\_D\TEST>cmdfaq 127
7F
As is seen the above can be easily generalized by changing the
"base" variable. The same goes for the other cases.
In the special case of DEC to HEX gawk inbuilt features can
alternatively be used as a simple shortcut:
@echo off & setlocal enableextensions
rem DEC to HEX
::
if "%~1"=="" (
echo.
echo Usage: %~f0 [DecimalNumber] to be converted to Hexadecimal
goto :EOF)
::
gawk 'BEGIN{printf"%%X\n","%~1"}'
::
endlocal & goto :EOF
The other way round the HEX to DEC code is
@echo off & setlocal enableextensions disabledelayedexpansion
rem HEX to DEC
::
:: Usage
if "%~1"=="" (
echo.
echo Usage: %~f0 [HexNumber] to be converted to Decimal
goto :EOF)
::
:: Build an awk source
set awksrc="%temp%\tmp$$$.awk"
> %awksrc% echo BEGIN{
>> %awksrc% echo k=1
>> %awksrc% echo d=0
>> %awksrc% echo base=16
>> %awksrc% echo number=toupper("%1")
>> %awksrc% echo i=length(number)+1
>> %awksrc% echo while(i!=1)
>> %awksrc% echo {
>> %awksrc% echo i--
>> %awksrc% echo j=index("123456789ABCDEF",substr(number,i,1))
>> %awksrc% echo d=d+j*k
>> %awksrc% echo k=base*k
>> %awksrc% echo }
>> %awksrc% echo printf"%%s in HEX is %%s in DEC\n",number,d
>> %awksrc% echo }
::
:: Run the awk source
gawk -f %awksrc%
::
:: Clean up
for %%f in (%awksrc%) do if exist %%f del %%f
endlocal & goto :EOF
An example of the output
C:\_D\TEST>cmdfaq FD
FD in HEX is 253 in DEC
Let's consider the conversion from decimal to binary and putting the
result into an environment variable.
@echo off & setlocal enableextensions
rem DEC to BIN
::
:: Usage
if "%~1"=="" (
echo.
echo Usage: %~f0 [DecimalNumber] to be converted to Binary
goto :EOF)
::
:: Build an awk source
set awksrc="%temp%\tmp$$$.awk"
> %awksrc% echo BEGIN{
>> %awksrc% echo number=%1
>> %awksrc% echo base=2
>> %awksrc% echo digit="0123456789ABCDEF"
>> %awksrc% echo result=""
>> %awksrc% echo while(number!=0)
>> %awksrc% echo {
>> %awksrc% echo i=number-base*int(number/base)
>> %awksrc% echo result=substr(digit,i+1,1)result
>> %awksrc% echo number=int(number/base)
>> %awksrc% echo }
>> %awksrc% echo printf"@set bin_=%%s\n",result
>> %awksrc% echo }
::
:: Run the awk source and the created command script
set myscript="%temp%\tmp$$$.cmd"
gawk -f %awksrc%>%myscript%
call %myscript%
::
:: Clean up
for %%f in (%awksrc% %myscript%) do if exist %%f del %%f
::
:: Display the results
echo %1 DEC = %bin_% BIN
endlocal & goto :EOF
An example of the output
C:\_D\TEST>cmdfaq 12
12 DEC = 1100 BIN
A VBScript-aided solution for the Decimal to Binary conversion is
given below
@echo off & setlocal enableextensions
rem DEC to BIN
::
:: Usage
if "%~1"=="" (
echo.
echo Usage: %~f0 [DecimalNumber] to be converted to Binary
goto :EOF)
::
:: Build a Visual Basic Script and run it with Microsoft Windows Script Host
findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
cscript //nologo "%temp%\tmp$$$.vbs" %1 > "%temp%\tmp$$$.cmd"
::
:: Utilize the output and display the result
call "%temp%\tmp$$$.cmd"
echo Decimal %1 in Binary = %bin_%
::
:: Clean up
for %%f in ("%temp%\tmp$$$.vbs" "%temp%\tmp$$$.cmd") do if exist %%f del %%f
endlocal & goto :EOF
'
number=WScript.Arguments.Unnamed(0) 'VBS
base=2 'VBS
digit="0123456789ABCDEF" 'VBS
result="" 'VBS
While number <> 0 'VBS
i = number - base * Int(number/base) 'VBS
result = Mid(digit,i+1,1) & result 'VBS
number = Int(number/base) 'VBS
Wend 'VBS
WScript.Echo "@set bin_=" & result 'VBS
An example of the output
C:\_D\TEST>cmdfaq 12
Decimal 12 in Binary = 1100
Since
VBScript has a Hex function, for the Decimal to Hexadecimal
the while loop and the three lines above it can simply be replaced
with
result = Hex(number) 'VBS
The same goes for octal.
To conclude the item one more VBScript-aided solution version:
@echo off & setlocal enableextensions
rem HEX to DEC
::
:: Usage
if "%~1"=="" (
echo.
echo Usage: %~f0 [HexNumber] to be converted to Decimal
goto :EOF)
::
:: Build a Visual Basic Script and run it with Microsoft Windows Script Host
findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
cscript //nologo "%temp%\tmp$$$.vbs" %1 > "%temp%\tmp$$$.cmd"
::
:: Utilize the output and display the result
call "%temp%\tmp$$$.cmd"
echo Hexadecimal %1 in Decimal = %dec_%
::
:: Clean up
for %%f in ("%temp%\tmp$$$.vbs" "%temp%\tmp$$$.cmd") do if exist %%f del %%f
endlocal & goto :EOF
'
number=WScript.Arguments.Unnamed(0) 'VBS
k = 1 'VBS
d = 0 'VBS
base = 16 'VBS
number=UCase(number) 'VBS
i = Len(number) + 1 'VBS
While i > 1 'VBS
i = i - 1 'VBS
j = Instr (1, "123456789ABCDEF", Mid(number,i,1), 0) 'VBS
d = d + (j * k) 'VBS
k = base * k 'VBS
Wend 'VBS
WScript.Echo "@set dec_=" & d 'VBS
An example of the output
C:\_D\TEST>cmdfaq 1a
Hexadecimal 1a in Decimal = 26
Written slightly differently
@echo off & setlocal enableextensions
rem HEX to DEC
::
:: Usage
if "%~1"=="" (
echo.
echo Usage: %~f0 [HexNumber] to be converted to Decimal
goto :EOF)
::
:: Build a Visual Basic Script
:: and run it with Microsoft Windows Script Host
set skip=
findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
for /f "tokens=* delims=" %%a in (
'cscript //nologo "%temp%\tmp$$$.vbs" %1') do set dec_=%%a
::
:: Utilize the output and display the result
echo Hexadecimal %1 in Decimal = %dec_%
::
:: Clean up
for %%f in ("%temp%\tmp$$$.vbs") do if exist %%f del %%f
endlocal & goto :EOF
'
number=WScript.Arguments.Unnamed(0) 'VBS
k = 1 'VBS
d = 0 'VBS
base = 16 'VBS
number=UCase(number) 'VBS
i = Len(number) + 1 'VBS
While i > 1 'VBS
i = i - 1 'VBS
j = Instr (1, "123456789ABCDEF", Mid(number,i,1), 0) 'VBS
d = d + (j * k) 'VBS
k = base * k 'VBS
Wend 'VBS
WScript.Echo d 'VBS
Let's draw all this together for a real-life situation. I need a
single script that converts between the following bases: binary,
octal, decimal and hexadecimal. This is what I use.
(Why the name BASE7.CMD? Because on XP I have a 16-bit program
BASE.EXE for the same purpose. The current script is for my 64-bit
Windows 7 PC.)
@echo off & setlocal enableextensions
rem enabledelayedexpansion
rem C:\_F\XTOOLS\BASE7.CMD
rem FromBase ToBase Number
::
call :programTitle
set help_=
if "%~3"=="" set help_=true
if "%~1"=="?" set help_=true
if "%~1"=="/?" set help_=true
if defined help_ (
call :ProgramHelp
goto _out)
::
:: Assign a value for the temporary folder variable temp_
call :AssignTemp temp_
::
:: The awk program, customize as is relevant for you
:: No spaces allowed in the file path
set awkprog_=C:\_F\FTOOLS\
unxgawk.exe
call :CheckExistence Program "%awkprog_%" found_
if not defined found_ goto _out
::
call :CheckParam "%~1" "%~2" "%~3" invalid_
if defined invalid_ (
echo/
call :ProgramHelp
goto _out)
::
call :BaseToDec "%~3" "%~1" dec_
echo %~3 in base %~1 is %dec_% in decimal (base 10)
call :DecToBase "%dec_%" "%~2" x_
echo %dec_% in base 10 (decimal) is %x_% in base %~2
echo Thus %~3 in base %~1 is %x_% in base %~2
::
:_out
if not defined cmdbox if defined PauseIfFromDesktop pause
endlocal & goto :EOF
:ProgramTitle
echo/
echo +-----------------------------------------------------+
echo ¦ BASE7.CMD Convert numbers between different bases ¦
echo ¦ By Prof. Timo Salmi, Last modified Fri 2-Jan-2015 ¦
echo +-----------------------------------------------------+
echo/
goto :EOF
:ProgramHelp
echo Usage: BASE7 FromBase ToBase Number
echo/
echo Works best for bases 2, 8, 10, and 16
goto :EOF
:AssignTemp
setlocal
set return_=%temp%
if defined mytemp if exist "%mytemp%\" set return_=%mytemp%
endlocal & set "%1=%return_%" & goto :EOF
:DecToBase
setlocal enableextensions disabledelayedexpansion
set awksrc=%temp_%\tmp$$$.awk
> "%awksrc%" echo BEGIN{
>> "%awksrc%" echo number=%~1
>> "%awksrc%" echo base=%~2
>> "%awksrc%" echo digit="0123456789ABCDEF"
>> "%awksrc%" echo result=""
>> "%awksrc%" echo while(number!=0)
>> "%awksrc%" echo {
>> "%awksrc%" echo i=number-base*int(number/base)
>> "%awksrc%" echo result=substr(digit,i+1,1)result
>> "%awksrc%" echo number=int(number/base)
>> "%awksrc%" echo }
>> "%awksrc%" echo printf"%%s\n",result
>> "%awksrc%" echo }
::
:: Run the awk source
for /f "usebackq" %%a in (`%awkprog_% -f "%awksrc%"`) do set return_=%%a
::
:: Clean up
for %%f in ("%awksrc%") do if exist %%f del %%f
endlocal & set "%3=%return_%" & goto :EOF
:BaseToDec
setlocal enableextensions disabledelayedexpansion
set awksrc=%temp_%\tmp$$$.awk
> "%awksrc%" echo BEGIN{
>> "%awksrc%" echo k=1
>> "%awksrc%" echo d=0
>> "%awksrc%" echo base=%~2
>> "%awksrc%" echo number=toupper("%~1")
>> "%awksrc%" echo i=length(number)+1
>> "%awksrc%" echo while(i!=1)
>> "%awksrc%" echo {
>> "%awksrc%" echo i--
>> "%awksrc%" echo j=index("123456789ABCDEF",substr(number,i,1))
>> "%awksrc%" echo d=d+j*k
>> "%awksrc%" echo k=base*k
>> "%awksrc%" echo }
>> "%awksrc%" echo printf"%%s\n",d
>> "%awksrc%" echo }
::
:: Run the awk source
for /f "usebackq" %%a in (`%awkprog_% -f "%awksrc%"`) do set return_=%%a
::
:: Clean up
for %%f in ("%awksrc%") do if exist %%f del %%f
endlocal & set "%3=%return_%" & goto :EOF
:: Perform some input parameter validity checking, not airtight
:CheckParam
setlocal enableextensions
set invalid_=
::
echo %~1|findstr /r "[^0-9]">nul
if %errorlevel% EQU 0 (
set invalid_=true
echo FromBase %~1 contains invalid characters
goto _eofCheckParam)
::
echo %~2|findstr /r "[^0-9]">nul
if %errorlevel% EQU 0 (
echo ToBase %~2 contains invalid characters
set invalid_=true
goto _eofCheckParam)
::
echo %~3|findstr /r "[^0-9^a-f^A-F]">nul
if %errorlevel% EQU 0 (
echo The number to be converted %~3 contains invalid characters
set invalid_=true
goto _eofCheckParam)
::
if %~1 LEQ 1 (
set invalid_=true
echo The value %~1 of FromBase is less than 2
goto _eofCheckParam)
if %~2 LEQ 1 (
set invalid_=true
echo Thealue %~2 of ToBase is less than 2
goto _eofCheckParam)
::
if %~1 GTR 16 (
set invalid_=true
echo The value %~1 of FromBase is greater than 16
goto _eofCheckParam)
if %~2 GTR 16 (
set invalid_=true
echo The value %~2 of ToBase is greater than 16
goto _eofCheckParam)
if %~3 LSS 0 (
set invalid_=true
echo The value %~3 is negative
goto _eofCheckParam)
::
echo %~3|findstr /r "[^0-9]">nul
if %errorlevel% EQU 0 if "%~1"=="10" (
set invalid_=true
echo The value to be convereted %~3 contains chracters outside the decimal base
goto _eofCheckParam)
::
echo %~3|findstr /r "[^0-7]">nul
if %errorlevel% EQU 0 if "%~1"=="8" (
set invalid_=true
echo The value to be convereted %~3 contains chracters outside the octal base
goto _eofCheckParam)
::
echo %~3|findstr /r "[^0-1]">nul
if %errorlevel% EQU 0 if "%~1"=="2" (
set invalid_=true
echo The value to be convereted %~3 contains chracters outside the binary base
goto _eofCheckParam)
::
:_eofCheckParam
endlocal & set "%4=%invalid_%" & goto :EOF
:CheckExistence
setlocal enableextensions
set file_=%2
if exist %file_% (endlocal & set "%3=true" & goto :EOF)
echo %~1 %file_% not found
endlocal & set "%3=" & goto :EOF
:: For debugging, show verbally the value of an environment variable
:ShowVarValue TheNameOfTheVariable
setlocal
set par1_=%~1
call set value_=%%%par1_%%%
echo The value of %~1 is %value_%
endlocal & goto :EOF
The output might be e.g.
C:\_D\TEST>base7 16 8 FE
+-----------------------------------------------------+
¦ BASE8.CMD Convert numbers between different bases ¦
¦ By Prof. Timo Salmi, Last modified Fri 2-Jan-2015 ¦
+-----------------------------------------------------+
FE in base 16 is 254 in decimal (base 10)
254 in base 10 (decimal) is 376 in base 8
Thus FE in base 16 is 376 in base 8