I will start by stating that it's not my original idea, but taken
from Erlang. See Erlang's io:format documentation here:
http://www.erlang.org/doc/man/io.html#format-1 and notice the 'B'
control sequence.
I would like to have an easy built-in way to print integers in
different bases (radices). There are so many half baked solutions
out there:
http://bugs.python.org/issue6783
http://stackoverflow.com/questions/2267362/convert-integer-to-a-string-in-a-given-numeric-base-in-python
http://stackoverflow.com/questions/2063425/python-elegant-inverse-function-of-intstring-base
http://code.activestate.com/recipes/65212/
I suggest using the precision field in the format specification
for integers for that. Examples:
"{:.16d}".format(31) #Prints '1f'
"{:.2d}".format(-19) # Prints '-10011'
"{:.36d}".format(36*5 + 35) #Prints '5Z'
"{:.3d}".format(26) # Prints '222'
The are good reasons for doing so:
1. Convenience. Instead of using a function for doing the
conversion, it will always be easier to use the built-in format()
function.
2. Elegance. There is already an *input* function for numbers in
different bases; It is called int(). Symmetry is usually elegant,
so will adding an *output* function for numbers in different
bases.
3. It is almost there! There is already an internal function in
CPython to convert to decimal base. See long_to_decimal_string() in
http://hg.python.org/cpython/file/8d60c1c89105/Objects/longobject.c
or the easier to understand int_to_decimal_string()
in
http://hg.python.org/cpython/file/86f699766016/Objects/intobject.c
and notice the comment there.
4. It doesn't break anything. As written in
http://docs.python.org/py3k/library/string.html#format-specification-mini-language:
"...The precision is not allowed for integer values". No
valid older code use it.
Some nitty gritty details:
1. The base will be only between 2 and 36. Like what int()
allows. The default base is 10.
2. Adding 'D' integer presentation type for uppercase in bases
larger than 10.
3. It might be a nice mnemonic using 'b' instead, standing for
'base'. Then the default base will be 2.
4. There should be a decision what to do with '#' alternate form
option. I think that only for the current bases with a prefix (2,
8 and 16) the prefix would be printed. Notice that it also
elegantly solves the problem of printing the '0B' and '0O'
prefixes. They are legal in Python, but there is no pythonic way
to print them.
5. What happens when you want to decide the base at run-time?
Maybe doing something like in C's printf():
http://c-faq.com/stdio/printfvwid.html where there is a count
before the actual number to print. So that "{:.*d}".format(16,
256) will print '100'. Doing so opens a door for crazier ideas. If
the '*' is followed by a number the base will be taken from the
positional argument at that number. If the '*' is followed by a
somehow-quoted valid identifier, the base will be taken from a
keyword argument with that name. It is handy for using the same
base for several numbers: "{0:.*2d} {1:.*2d} {4:.*{current_base}d}
{5:.*{current_base}d}".format(256, 16, 16, 26, 25, current_base=3)
will print "100 10 222 221". The 2 in {0:.*2d} refers for the
second 16.
What do you think?
Regards,
TB
P.S. Bonus question: What "{:.-909d}".format(42) would print?