## FANDOM

1,639 Pages

Tip 27 Printable Monobook Previous Next

created 2001 · complexity basic · version 7.0

This tip shows how to convert numbers from hexadecimal to decimal, and the reverse. A variety of methods are given, including some simple commands you can enter, and some scripts to easily replace hex numbers with decimal, or to replace decimal with hex. Handling percent-encoded text is also discussed, and there are links to tips showing how to edit a binary file in hex.

## Commands Edit

Occasional conversions can be performed by entering commands. In Vim, put the cursor on 0x12345 and type `:echo` then Space Ctrl-R Ctrl-W Enter. That will execute `:echo 0x12345` which displays 74565 (decimal equivalent of hex 12345).

An example of converting decimal to hex would be to enter `:echo printf('%x',74565)` which displays 12345 (hex equivalent of decimal 74565).

In addition, the expression register can be used to enter converted numbers while typing. In insert mode, press Ctrl-R then `=` then the expression wanted, then press Enter. The value of the expression is inserted, and you will remain in insert mode. For example, `<C-R>=0x09ab<Enter>` will insert `2475`, and `<C-R>=printf('0x%04x',2475)<Enter>` will insert `0x09ab`.

In normal mode, type `ga` to display the decimal and hex values for the character under the cursor, or type `g8` to display the hex bytes for a UTF-8 character.

The following commands illustrate other simple techniques to convert strings to numbers which are displayed in decimal (the `:echo` is just for illustration; these techniques would be used in a script). The first shows that adding zero to a string converts the string to a number.

Command Output Description
`:echo '0012' + 0` 10 octal 12 due to leading zero
`:echo str2nr('0012')` 12 decimal 12 (leading zeros ignored)
`:echo str2nr('0x0a2f', 16)` 2607 hex a2f
`:echo str2nr('0a2f', 16)` 2607 same ('0x' not required with base 16)
`:echo str2nr('^R^W', 16)` (decimal) hex word under cursor (press Ctrl-R Ctrl-W)

The following convert decimal numbers to hex strings.

Command Output Description
`:echo printf('%x', 1234)` 4d2 decimal 1234 in hex
`:echo printf('%04x', 1234)` 04d2 same, with leading zeros to four digits
`:echo printf('%x', ^R^W)` (hex) decimal word under cursor (press Ctrl-R Ctrl-W)

## Copying a hex number as decimal Edit

With the following mapping, you can put the cursor on a hex number and press `\h` (assuming the default backslash leader) to yank the value of the hex number (using `:let` means the equivalent decimal string is copied). You can then move the cursor elsewhere and press `p` to paste the decimal value.

```nnoremap \h :let @@=<C-R><C-W><CR>
```

Alternatively, you can use a global variable to avoid using a register. With these mappings, `\h` will yank a hex value, and `\p` will paste the decimal string:

```nnoremap \h :let Value=<C-R><C-W><CR>
nnoremap \p :if exists('Value')<Bar>normal i<C-R>=Value<CR><Esc><Bar>:endif<CR>
```

## User commands Edit

Put the following in your vimrc to define user commands to convert between hex and decimal. You can convert a number entered on the command line, or all numbers in selected text.

```command! -nargs=? -range Dec2hex call s:Dec2hex(<line1>, <line2>, '<args>')
function! s:Dec2hex(line1, line2, arg) range
if empty(a:arg)
if histget(':', -1) =~# "^'<,'>" && visualmode() !=# 'V'
let cmd = 's/\%V\<\d\+\>/\=printf("0x%x",submatch(0)+0)/g'
else
let cmd = 's/\<\d\+\>/\=printf("0x%x",submatch(0)+0)/g'
endif
try
execute a:line1 . ',' . a:line2 . cmd
catch
echo 'Error: No decimal number found'
endtry
else
echo printf('%x', a:arg + 0)
endif
endfunction

command! -nargs=? -range Hex2dec call s:Hex2dec(<line1>, <line2>, '<args>')
function! s:Hex2dec(line1, line2, arg) range
if empty(a:arg)
if histget(':', -1) =~# "^'<,'>" && visualmode() !=# 'V'
let cmd = 's/\%V0x\x\+/\=submatch(0)+0/g'
else
let cmd = 's/0x\x\+/\=submatch(0)+0/g'
endif
try
execute a:line1 . ',' . a:line2 . cmd
catch
echo 'Error: No hex number starting "0x" found'
endtry
else
echo (a:arg =~? '^0x') ? a:arg + 0 : ('0x'.a:arg) + 0
endif
endfunction
```

The above defines user commands `:Dec2hex` and `:Hex2dec` that will either display the result of converting a number that you enter, or will convert all numbers in selected text. A decimal number is a word consisting only of decimal digits, while a hex number consists of "0x" followed by one or more hex digits.

If no argument is entered with these commands, a range may be specified. The default range is the current line. A visual selection (character, line, or block) can also specify a range. When using a visual block (selection starts with Ctrl-V, or Ctrl-Q if Ctrl-V is used for paste), only numbers inside the block are converted. Example commands:

Command Description
`:Dec2hex 496` Displays 1f0 (hex equivalent of decimal 496).
`:Dec2hex` Converts all decimal numbers to hex in current line.
`:'<,>'Dec2hex` Same, for all visually selected text (v, V, or ^V).
`:%Dec2hex` Same, for all lines in buffer.
`:Hex2dec 0x1f0` Displays 496 (decimal equivalent of hex 1f0).
`:Hex2dec 1f0` Same ("0x" is optional in an argument).
`:Hex2dec` Converts all "0x" hex numbers to decimal in current line.
`:'<,>'Hex2dec` Same, for all visually selected text (v, V, or ^V).
`:%Hex2dec` Same, for all lines in buffer.

This version handles up to 32-bit long integers. An extended version of this script that works for arbitrary sized integers is available as a plugin on Github.

## Converting strings Edit

Following are some methods for working with percent-encoded text, and for showing ASCII characters in hex.

```" Convert current line to percent-encoded hex for disallowed punctuation.
" Example: line "A/CD\E" is converted to "A%2FC%5B123%5DD%5CE".
" Convert percent-encoded hex in current line to text (reverse of above).

" Convert each ASCII character in a string to hex bytes.
" Example: ":Str2hex ABC 123" displays "41 42 43 20 31 32 33".
command! -nargs=* Str2hex echo Str2hex(<q-args>)
function! Str2hex(arg)
return join(map(split(a:arg, '\zs'), 'printf("%02x", char2nr(v:val))'))
endfunction
```

## General functions Edit

A script could use the following functions for conversions between decimal and hex.

```" Return hex string equivalent to given decimal string or number.
function! Dec2hex(arg)
return printf('%x', a:arg + 0)
endfunction

" Return number equivalent to given hex string ('0x' is optional).
function! Hex2dec(arg)
return (a:arg =~? '^0x') ? a:arg + 0 : ('0x'.a:arg) + 0
endfunction
```

Sometimes one just needs to know the value of decimal/hexadecimal value, without changing the text. Put the following in your vimrc to define user command 'gn' to print the number under the cursor converted to hex/decimal (similar to built-in command 'ga' and 'g8' for ASCII character under the cursor):

```nnoremap gn :call DecAndHex(expand("<cWORD>"))<CR>

function! DecAndHex(number)
let ns = '[.,;:''"<>()^_lL]'      " number separators
if a:number =~? '^' . ns. '*[-+]\?\d\+' . ns . '*\$'
let dec = substitute(a:number, '[^0-9+-]*\([+-]\?\d\+\).*','\1','')
echo dec . printf('  ->  0x%X, -(0x%X)', dec, -dec)
elseif a:number =~? '^' . ns. '*\%\(h''\|0x\|#\)\?\(\x\+\)' . ns . '*\$'
let hex = substitute(a:number, '.\{-}\%\(h''\|0x\|#\)\?\(\x\+\).*','\1','')
echon '0x' . hex . printf('  ->  %d', eval('0x'.hex))
if strpart(hex, 0,1) =~? '[89a-f]' && strlen(hex) =~? '2\|4\|6'
" for 8/16/24 bits numbers print the equivalent negative number
echon ' ('. float2nr(eval('0x'. hex) - pow(2,4*strlen(hex))) . ')'
endif
echo
else
echo "NaN"
endif
endfunction
```

Numbers containing character A-F or prefixed with '0x', 'h' or '#' are treated as hexadecimal values:

WORD under cursor Output Description
`32` 32 -> 0x20, -(0xFFFFFFE0) decimal 32 in hex, decimal -32 in hex
`-32` -32 -> 0xFFFFFFE0, -(0x20) decimal -32 in hex, decimal 32 in hex
`0x32` 0x32 -> 50 hex 32 in decimal
`h'38` 0x38 -> 56 hex 38 in decimal
`#123` 0x123 -> 291 hex 123 in decimal
`0xFFFFFFE0` 0xFFFFFFE0 -> -32 32 bit hex FFFFFFE0 in decimal
`0xFFFE00` 0xFFFE00 -> 16776704 (-512) hex FFFE00 in decimal, equivalent negative value on a 24 bits machine
`ab` 0xab -> 171 (-85) hex ab in decimal, equivalent negative value on a 8 bits machine

## Using external programs Edit

TO DO

• Fix or delete this section.
• The following is from old tip 772. It does not seem helpful, but we should discuss the menus somewhere so I am keeping the text for a while.

This example creates a menu for conversions using the bc calculator which is a standard utility on many Unix-based systems. Visually select the number (without leading '0x'), right click the selection, and select from the popup menu to transform the number.

```vmenu 1.220 PopUp.&nr2hex <Esc>:exec("!echo \\"obase=16;".@*."\\" \| bc -l -q ")<CR>
vmenu 1.220 PopUp.hex&2nr <Esc>:exec("!echo \\"ibase=16;".toupper(@*)."\\" \| bc -l -q ")<CR>
```

More is needed to make it work. I had to do the following on a Linux system, but I suspect a setting regarding register `*` is also being used (it assumes that the selected text is in the `*` register).

```set mousemodel=popup
vmenu 1.220 PopUp.&nr2hex <Esc>:exec '!echo "obase=16;'.@*.'" \| bc -l -q '<CR>
vmenu 1.220 PopUp.hex&2nr <Esc>:exec '!echo "ibase=16;'.toupper(@*).'" \| bc -l -q '<CR>
```

## Comments Edit

Community content is available under CC-BY-SA unless otherwise noted.