Python: How to increment a special-purpose string? - python

Consider a special-purpose string of length 8, say "A00000XY". The string has following restrictions.
Length = 8.
Last two chars have special meaning and should remain as it is.
A-Z and 0-9 are only valid characters. Thus the regular expression "^[A-Z0-9]{6}XY$" defines the string.
How can I implement a function, say increment, that when called increments the string by one. Thus subsequent calls should look like following:
>>> A = "A00000XY"
>>> print increment(A)
"A00000XY"
>>> print increment(A)
"A00001XY"
>>> print increment(A)
"A00002XY"
...
>>> print increment(A)
"A00009XY"
>>> print increment(A)
"A0000AXY"
>>> print increment(A)
"A0000BXY"
...
>>> print increment(A)
"A0000YXY"
>>> print increment(A)
"A0000ZXY"
>>> print increment(A)
"A00010XY"
>>> print increment(A)
"A00011XY"
...
>>> print increment(A)
"ZZZZZZXY"

digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def digit_helper(num):
while num > 0:
yield digits[num % 36]
num = num / 36
def increment(string):
incremented = int(string[:-2], base=36) + 1
return "".join(reversed(list(digit_helper(incremented)))) + "XY"
Temptation was too high. However, not very suitable as homework answer, I'm afraid :D
Update: it's Python 2. In Python 3 division should be num // 36.

So what you really want is a base 36 number. You will need to build a class that works similar to how hex to decimal and decimal to hex conversions work. With your 8 character limit, you have values from 0 to 36^8 - 1 values, or 2821109907455.
9223372036854775807 is the max integer in python , so the good news is that you can represent your value as an integer.
To convert from your string value to the integer:
intValue = 0
Loop through each of the first eight characters in the string.
Pass the character to a function that returns an integer equivalent between 0 and 35. We'll call this charValue
intValue += intValue*36 + charValue
To convert from the integer to your string value:
stringValue = specialCharacters
curDigit = intValue % 36
intValue = intValue / 36
find string equivalent of intValue (0 to Z)
Append to front of stringValue
Repeat until intValue < 36. Any remaining characters would be 0
Obviously you would build the increment and decrement methods as well.

Inspired from #avysk response.
The #avysk reply has two issues.
Handling for ZZZZZZXY. It should wrap around and return 000000XY. It shouldn't overflow. However I missed covering this part in my question itself.
000000XY isn't handled properly to return 000001XY. It instead
returns 1XY.
Fixing these issue in following code that borrows most from #avysk's response.
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def digit_helper(num):
while num > 0:
yield Tape.digits[num % 36]
num = num / 36
# This function, using the utility digit_helper, increments the string by 1.
# It produces string in following order:
# "A00000XY", "A00000XY", "A00001XY", "A00002XY", ...,
# "A00009XY", "A0000AXY", "A0000BXY", ...,
# "A0000YXY", "A0000ZXY", "A00010XY", "A00011XY", ...,
# "ZZZZZZXY", "000000XY", "000001XY", ...
# Logic:
# 1. Strip the string of last two chars.
# 2. Convert to base 36 equivalent integer and increment by one.
# 3. Convert back to Base 36 representation of incremented value.
# 3.1. [0:6] handles the overflow. Overflow happens after "ZZZZZZXY" and produces "1000000XY".
# 3.2. [::-1] reverses the string.
# 3.3. zfill(6) handles underflow, like converting integer 1 to "000001XY".
def increment(string):
incremented = int(string[:-2], base=36) + 1
return "".join(Tape.digit_helper(incremented))[0:6][::-1].zfill(6) + string[-2:]

Related

Zylabs 7.14 Lab: Reverse binary [duplicate]

Are there any canned Python methods to convert an Integer (or Long) into a binary string in Python?
There are a myriad of dec2bin() functions out on Google... But I was hoping I could use a built-in function / library.
Python's string format method can take a format spec.
>>> "{0:b}".format(37)
'100101'
Format spec docs for Python 2
Format spec docs for Python 3
If you're looking for bin() as an equivalent to hex(), it was added in python 2.6.
Example:
>>> bin(10)
'0b1010'
Python actually does have something already built in for this, the ability to do operations such as '{0:b}'.format(42), which will give you the bit pattern (in a string) for 42, or 101010.
For a more general philosophy, no language or library will give its user base everything that they desire. If you're working in an environment that doesn't provide exactly what you need, you should be collecting snippets of code as you develop to ensure you never have to write the same thing twice. Such as, for example, the pseudo-code:
define intToBinString, receiving intVal:
if intVal is equal to zero:
return "0"
set strVal to ""
while intVal is greater than zero:
if intVal is odd:
prefix "1" to strVal
else:
prefix "0" to strVal
divide intVal by two, rounding down
return strVal
which will construct your binary string based on the decimal value. Just keep in mind that's a generic bit of pseudo-code which may not be the most efficient way of doing it though, with the iterations you seem to be proposing, it won't make much difference. It's really just meant as a guideline on how it could be done.
The general idea is to use code from (in order of preference):
the language or built-in libraries.
third-party libraries with suitable licenses.
your own collection.
something new you need to write (and save in your own collection for later).
If you want a textual representation without the 0b-prefix, you could use this:
get_bin = lambda x: format(x, 'b')
print(get_bin(3))
>>> '11'
print(get_bin(-3))
>>> '-11'
When you want a n-bit representation:
get_bin = lambda x, n: format(x, 'b').zfill(n)
>>> get_bin(12, 32)
'00000000000000000000000000001100'
>>> get_bin(-12, 32)
'-00000000000000000000000000001100'
Alternatively, if you prefer having a function:
def get_bin(x, n=0):
"""
Get the binary representation of x.
Parameters
----------
x : int
n : int
Minimum number of digits. If x needs less digits in binary, the rest
is filled with zeros.
Returns
-------
str
"""
return format(x, 'b').zfill(n)
I am surprised there is no mention of a nice way to accomplish this using formatting strings that are supported in Python 3.6 and higher. TLDR:
>>> number = 1
>>> f'0b{number:08b}'
'0b00000001'
Longer story
This is functionality of formatting strings available from Python 3.6:
>>> x, y, z = 1, 2, 3
>>> f'{x} {y} {2*z}'
'1 2 6'
You can request binary as well:
>>> f'{z:b}'
'11'
Specify the width:
>>> f'{z:8b}'
' 11'
Request zero padding:
f'{z:08b}'
'00000011'
And add common prefix to signify binary number:
>>> f'0b{z:08b}'
'0b00000011'
You can also let Python add the prefix for you but I do not like it so much as the version above because you have to take the prefix into width consideration:
>>> f'{z:#010b}'
'0b00000011'
More info is available in official documentation on Formatted string literals and Format Specification Mini-Language.
As a reference:
def toBinary(n):
return ''.join(str(1 & int(n) >> i) for i in range(64)[::-1])
This function can convert a positive integer as large as 18446744073709551615, represented as string '1111111111111111111111111111111111111111111111111111111111111111'.
It can be modified to serve a much larger integer, though it may not be as handy as "{0:b}".format() or bin().
This is for python 3 and it keeps the leading zeros !
print(format(0, '08b'))
A simple way to do that is to use string format, see this page.
>> "{0:b}".format(10)
'1010'
And if you want to have a fixed length of the binary string, you can use this:
>> "{0:{fill}8b}".format(10, fill='0')
'00001010'
If two's complement is required, then the following line can be used:
'{0:{fill}{width}b}'.format((x + 2**n) % 2**n, fill='0', width=n)
where n is the width of the binary string.
one-liner with lambda:
>>> binary = lambda n: '' if n==0 else binary(n/2) + str(n%2)
test:
>>> binary(5)
'101'
EDIT:
but then :(
t1 = time()
for i in range(1000000):
binary(i)
t2 = time()
print(t2 - t1)
# 6.57236599922
in compare to
t1 = time()
for i in range(1000000):
'{0:b}'.format(i)
t2 = time()
print(t2 - t1)
# 0.68017411232
As the preceding answers mostly used format(),
here is an f-string implementation.
integer = 7
bit_count = 5
print(f'{integer:0{bit_count}b}')
Output:
00111
For convenience here is the python docs link for formatted string literals: https://docs.python.org/3/reference/lexical_analysis.html#f-strings.
Summary of alternatives:
n=42
assert "-101010" == format(-n, 'b')
assert "-101010" == "{0:b}".format(-n)
assert "-101010" == (lambda x: x >= 0 and str(bin(x))[2:] or "-" + str(bin(x))[3:])(-n)
assert "0b101010" == bin(n)
assert "101010" == bin(n)[2:] # But this won't work for negative numbers.
Contributors include John Fouhy, Tung Nguyen, mVChr, Martin Thoma. and Martijn Pieters.
>>> format(123, 'b')
'1111011'
For those of us who need to convert signed integers (range -2**(digits-1) to 2**(digits-1)-1) to 2's complement binary strings, this works:
def int2bin(integer, digits):
if integer >= 0:
return bin(integer)[2:].zfill(digits)
else:
return bin(2**digits + integer)[2:]
This produces:
>>> int2bin(10, 8)
'00001010'
>>> int2bin(-10, 8)
'11110110'
>>> int2bin(-128, 8)
'10000000'
>>> int2bin(127, 8)
'01111111'
you can do like that :
bin(10)[2:]
or :
f = str(bin(10))
c = []
c.append("".join(map(int, f[2:])))
print c
Using numpy pack/unpackbits, they are your best friends.
Examples
--------
>>> a = np.array([[2], [7], [23]], dtype=np.uint8)
>>> a
array([[ 2],
[ 7],
[23]], dtype=uint8)
>>> b = np.unpackbits(a, axis=1)
>>> b
array([[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)
Yet another solution with another algorithm, by using bitwise operators.
def int2bin(val):
res=''
while val>0:
res += str(val&1)
val=val>>1 # val=val/2
return res[::-1] # reverse the string
A faster version without reversing the string.
def int2bin(val):
res=''
while val>0:
res = chr((val&1) + 0x30) + res
val=val>>1
return res
numpy.binary_repr(num, width=None)
Examples from the documentation link above:
>>> np.binary_repr(3)
'11'
>>> np.binary_repr(-3)
'-11'
>>> np.binary_repr(3, width=4)
'0011'
The two’s complement is returned when the input number is negative and width is specified:
>>> np.binary_repr(-3, width=3)
'101'
>>> np.binary_repr(-3, width=5)
'11101'
The accepted answer didn't address negative numbers, which I'll cover.
In addition to the answers above, you can also just use the bin and hex functions. And in the opposite direction, use binary notation:
>>> bin(37)
'0b100101'
>>> 0b100101
37
But with negative numbers, things get a bit more complicated. The question doesn't specify how you want to handle negative numbers.
Python just adds a negative sign so the result for -37 would be this:
>>> bin(-37)
'-0b100101'
In computer/hardware binary data, negative signs don't exist. All we have is 1's and 0's. So if you're reading or producing binary streams of data to be processed by other software/hardware, you need to first know the notation being used.
One notation is sign-magnitude notation, where the first bit represents the negative sign, and the rest is the actual value. In that case, -37 would be 0b1100101 and 37 would be 0b0100101. This looks like what python produces, but just add a 0 or 1 in front for positive / negative numbers.
More common is Two's complement notation, which seems more complicated and the result is very different from python's string formatting. You can read the details in the link, but with an 8bit signed integer -37 would be 0b11011011 and 37 would be 0b00100101.
Python has no easy way to produce these binary representations. You can use numpy to turn Two's complement binary values into python integers:
>>> import numpy as np
>>> np.int8(0b11011011)
-37
>>> np.uint8(0b11011011)
219
>>> np.uint8(0b00100101)
37
>>> np.int8(0b00100101)
37
But I don't know an easy way to do the opposite with builtin functions. The bitstring package can help though.
>>> from bitstring import BitArray
>>> arr = BitArray(int=-37, length=8)
>>> arr.uint
219
>>> arr.int
-37
>>> arr.bin
'11011011'
>>> BitArray(bin='11011011').int
-37
>>> BitArray(bin='11011011').uint
219
Python 3.6 added a new string formatting approach called formatted string literals or “f-strings”.
Example:
name = 'Bob'
number = 42
f"Hello, {name}, your number is {number:>08b}"
Output will be 'Hello, Bob, your number is 00001010!'
A discussion of this question can be found here - Here
Unless I'm misunderstanding what you mean by binary string I think the module you are looking for is struct
n=input()
print(bin(n).replace("0b", ""))
def binary(decimal) :
otherBase = ""
while decimal != 0 :
otherBase = str(decimal % 2) + otherBase
decimal //= 2
return otherBase
print binary(10)
output:
1010
Here is the code I've just implemented. This is not a method but you can use it as a ready-to-use function!
def inttobinary(number):
if number == 0:
return str(0)
result =""
while (number != 0):
remainder = number%2
number = number/2
result += str(remainder)
return result[::-1] # to invert the string
Calculator with all neccessary functions for DEC,BIN,HEX:
(made and tested with Python 3.5)
You can change the input test numbers and get the converted ones.
# CONVERTER: DEC / BIN / HEX
def dec2bin(d):
# dec -> bin
b = bin(d)
return b
def dec2hex(d):
# dec -> hex
h = hex(d)
return h
def bin2dec(b):
# bin -> dec
bin_numb="{0:b}".format(b)
d = eval(bin_numb)
return d,bin_numb
def bin2hex(b):
# bin -> hex
h = hex(b)
return h
def hex2dec(h):
# hex -> dec
d = int(h)
return d
def hex2bin(h):
# hex -> bin
b = bin(h)
return b
## TESTING NUMBERS
numb_dec = 99
numb_bin = 0b0111
numb_hex = 0xFF
## CALCULATIONS
res_dec2bin = dec2bin(numb_dec)
res_dec2hex = dec2hex(numb_dec)
res_bin2dec,bin_numb = bin2dec(numb_bin)
res_bin2hex = bin2hex(numb_bin)
res_hex2dec = hex2dec(numb_hex)
res_hex2bin = hex2bin(numb_hex)
## PRINTING
print('------- DECIMAL to BIN / HEX -------\n')
print('decimal:',numb_dec,'\nbin: ',res_dec2bin,'\nhex: ',res_dec2hex,'\n')
print('------- BINARY to DEC / HEX -------\n')
print('binary: ',bin_numb,'\ndec: ',numb_bin,'\nhex: ',res_bin2hex,'\n')
print('----- HEXADECIMAL to BIN / HEX -----\n')
print('hexadec:',hex(numb_hex),'\nbin: ',res_hex2bin,'\ndec: ',res_hex2dec,'\n')
Somewhat similar solution
def to_bin(dec):
flag = True
bin_str = ''
while flag:
remainder = dec % 2
quotient = dec / 2
if quotient == 0:
flag = False
bin_str += str(remainder)
dec = quotient
bin_str = bin_str[::-1] # reverse the string
return bin_str
here is simple solution using the divmod() fucntion which returns the reminder and the result of a division without the fraction.
def dectobin(number):
bin = ''
while (number >= 1):
number, rem = divmod(number, 2)
bin = bin + str(rem)
return bin
Here's yet another way using regular math, no loops, only recursion. (Trivial case 0 returns nothing).
def toBin(num):
if num == 0:
return ""
return toBin(num//2) + str(num%2)
print ([(toBin(i)) for i in range(10)])
['', '1', '10', '11', '100', '101', '110', '111', '1000', '1001']
To calculate binary of numbers:
print("Binary is {0:>08b}".format(16))
To calculate the Hexa decimal of a number:
print("Hexa Decimal is {0:>0x}".format(15))
To Calculate all the binary no till 16::
for i in range(17):
print("{0:>2}: binary is {0:>08b}".format(i))
To calculate Hexa decimal no till 17
for i in range(17):
print("{0:>2}: Hexa Decimal is {0:>0x}".format(i))
##as 2 digit is enogh for hexa decimal representation of a number
try:
while True:
p = ""
a = input()
while a != 0:
l = a % 2
b = a - l
a = b / 2
p = str(l) + p
print(p)
except:
print ("write 1 number")
I found a method using matrix operation to convert decimal to binary.
import numpy as np
E_mat = np.tile(E,[1,M])
M_order = pow(2,(M-1-np.array(range(M)))).T
bindata = np.remainder(np.floor(E_mat /M_order).astype(np.int),2)
Eis input decimal data,M is the binary orders. bindata is output binary data, which is in a format of 1 by M binary matrix.

Decimal To Binary Python Getting an Extra Zero In Return String

This is for a school project. I need to create a function using recursion to convert an integer to binary string. It must be a str returned, not an int. The base case is n==0, and then 0 would need to be returned. There must be a base case like this, but this is where I think I am getting the extra 0 from (I could be wrong). I am using Python 3.6 with the IDLE and the shell to execute it.
The function works just fine, expect for this additional zero that I need gone.
Here is my function, dtobr:
def dtobr(n):
"""
(int) -> (str)
This function has the parameter n, which is a non-negative integer,
and it will return the string of 0/1's
which is the binary representation of n. No side effects.
Returns bianry string as mentioned. This is like the function
dtob (decimal to bianary) but this is using recursion.
Examples:
>>> dtob(27)
'11011'
>>> dtob(0)
'0'
>>> dtob(1)
'1'
>>> dtob(2)
'10'
"""
if n == 0:
return str(0)
return dtobr(n // 2) + str(n % 2)
This came from the function I already wrote which converted it just fine, but without recursion. For reference, I will include this code as well, but this is not what I need for this project, and there are no errors with this:
def dtob(n):
"""
(int) -> (str)
This function has the parameter n, which is a non-negative integer,
and it will return the string of 0/1's
which is the binary representation of n. No side effects.
Returns bianry string as mentioned.
Examples:
>>> dtob(27)
'11011'
>>> dtob(0)
'0'
>>> dtob(1)
'1'
>>> dtob(2)
'10'
"""
string = ""
if n == 0:
return str(0)
while n > 0:
remainder = n % 2
string = str(remainder) + string
n = n // 2
Hopefully someone can help me get ride of that additional left hand zero. Thanks!
You need to change the condition to recursively handle both the n // 2 and n % 2:
if n <= 1:
return str(n) # per #pault's suggestion, only needed str(n) instead of str(n % 2)
else:
return dtobr(n // 2) + dtobr(n % 2)
Test case:
for i in [0, 1, 2, 27]:
print(dtobr(i))
# 0
# 1
# 10
# 11011
FYI you can easily convert to binary format like so:
'{0:b}'.format(x) # where x is your number
Since there is already an answer that points and resolves the issue with recursive way, lets see some interesting ways to achieve same goal.
Lets define a generator that will give us iterative way of getting binary numbers.
def to_binary(n):
if n == 0: yield "0"
while n > 0:
yield str(n % 2)
n = n / 2
Then you can use this iterable to get decimal to binary conversion in multiple ways.
Example 1.
reduce function is used to concatenate chars received from to_binary iterable (generator).
from functools import reduce
def to_binary(n):
if n == 0: yield "0"
while n > 0:
yield str(n % 2)
n = n / 2
print reduce(lambda x, y: x+y, to_binary(0)) # 0
print reduce(lambda x, y: x+y, to_binary(15)) # 1111
print reduce(lambda x, y: x+y, to_binary(15)) # 11011
Example 2.
join takes iterable, unrolls it and joins them by ''
def to_binary(n):
if n == 0: yield "0"
while n > 0:
yield str(n % 2)
n = n / 2
print ''.join(to_binary(0)) # 0
print ''.join(to_binary(1)) # 1
print ''.join(to_binary(15)) # 1111
print ''.join(to_binary(27)) # 11011

Decorating Hex function to pad zeros

I wrote this simple function:
def padded_hex(i, l):
given_int = i
given_len = l
hex_result = hex(given_int)[2:] # remove '0x' from beginning of str
num_hex_chars = len(hex_result)
extra_zeros = '0' * (given_len - num_hex_chars) # may not get used..
return ('0x' + hex_result if num_hex_chars == given_len else
'?' * given_len if num_hex_chars > given_len else
'0x' + extra_zeros + hex_result if num_hex_chars < given_len else
None)
Examples:
padded_hex(42,4) # result '0x002a'
hex(15) # result '0xf'
padded_hex(15,1) # result '0xf'
Whilst this is clear enough for me and fits my use case (a simple test tool for a simple printer) I can't help thinking there's a lot of room for improvement and this could be squashed down to something very concise.
What other approaches are there to this problem?
Use the new .format() string method:
>>> "{0:#0{1}x}".format(42,6)
'0x002a'
Explanation:
{ # Format identifier
0: # first parameter
# # use "0x" prefix
0 # fill with zeroes
{1} # to a length of n characters (including 0x), defined by the second parameter
x # hexadecimal number, using lowercase letters for a-f
} # End of format identifier
If you want the letter hex digits uppercase but the prefix with a lowercase 'x', you'll need a slight workaround:
>>> '0x{0:0{1}X}'.format(42,4)
'0x002A'
Starting with Python 3.6, you can also do this:
>>> value = 42
>>> padding = 6
>>> f"{value:#0{padding}x}"
'0x002a'
How about this:
print '0x%04x' % 42
If you don't need to handle negative numbers, you can do
"{:02x}".format(7) # '07'
"{:02x}".format(27) # '1b'
Where
: is the start of the formatting specification for the first argument {} to .format()
02 means "pad the input from the left with 0s to length 2"
x means "format as hex with lowercase letters"
You can also do this with f-strings:
f"{7:02x}" # '07'
f"{27:02x}" # '1b'
If just for leading zeros, you can try zfill function.
'0x' + hex(42)[2:].zfill(4) #'0x002a'
Use * to pass width and X for uppercase
print '0x%0*X' % (4,42) # '0x002A'
As suggested by georg and Ashwini Chaudhary
None of the answers are dealing well with negative numbers...
Try this:
val = 42
nbits = 16
'{:04X}'.format(val & ((1 << nbits)-1))
If you want to hold the preceding hex notation 0x you can also try this method too which is using the python3 f-strings.
f'0x{10:02x}' # 0x0a
Suppose you want to have leading zeros for hexadecimal number, for example you want 7 digit where your hexadecimal number should be written on, you can do like that :
hexnum = 0xfff
str_hex = hex(hexnum).rstrip("L").lstrip("0x") or "0"
'0'* (7 - len(str_hexnum)) + str_hexnum
This gives as a result :
'0000fff'

Convert hex to binary

I have ABC123EFFF.
I want to have 001010101111000001001000111110111111111111 (i.e. binary repr. with, say, 42 digits and leading zeroes).
How?
For solving the left-side trailing zero problem:
my_hexdata = "1a"
scale = 16 ## equals to hexadecimal
num_of_bits = 8
bin(int(my_hexdata, scale))[2:].zfill(num_of_bits)
It will give 00011010 instead of the trimmed version.
import binascii
binary_string = binascii.unhexlify(hex_string)
Read
binascii.unhexlify
Return the binary data represented by the hexadecimal string specified as the parameter.
Convert hex to binary
I have ABC123EFFF.
I want to have 001010101111000001001000111110111111111111 (i.e. binary
repr. with, say, 42 digits and leading zeroes).
Short answer:
The new f-strings in Python 3.6 allow you to do this using very terse syntax:
>>> f'{0xABC123EFFF:0>42b}'
'001010101111000001001000111110111111111111'
or to break that up with the semantics:
>>> number, pad, rjust, size, kind = 0xABC123EFFF, '0', '>', 42, 'b'
>>> f'{number:{pad}{rjust}{size}{kind}}'
'001010101111000001001000111110111111111111'
Long answer:
What you are actually saying is that you have a value in a hexadecimal representation, and you want to represent an equivalent value in binary.
The value of equivalence is an integer. But you may begin with a string, and to view in binary, you must end with a string.
Convert hex to binary, 42 digits and leading zeros?
We have several direct ways to accomplish this goal, without hacks using slices.
First, before we can do any binary manipulation at all, convert to int (I presume this is in a string format, not as a literal):
>>> integer = int('ABC123EFFF', 16)
>>> integer
737679765503
alternatively we could use an integer literal as expressed in hexadecimal form:
>>> integer = 0xABC123EFFF
>>> integer
737679765503
Now we need to express our integer in a binary representation.
Use the builtin function, format
Then pass to format:
>>> format(integer, '0>42b')
'001010101111000001001000111110111111111111'
This uses the formatting specification's mini-language.
To break that down, here's the grammar form of it:
[[fill]align][sign][#][0][width][,][.precision][type]
To make that into a specification for our needs, we just exclude the things we don't need:
>>> spec = '{fill}{align}{width}{type}'.format(fill='0', align='>', width=42, type='b')
>>> spec
'0>42b'
and just pass that to format
>>> bin_representation = format(integer, spec)
>>> bin_representation
'001010101111000001001000111110111111111111'
>>> print(bin_representation)
001010101111000001001000111110111111111111
String Formatting (Templating) with str.format
We can use that in a string using str.format method:
>>> 'here is the binary form: {0:{spec}}'.format(integer, spec=spec)
'here is the binary form: 001010101111000001001000111110111111111111'
Or just put the spec directly in the original string:
>>> 'here is the binary form: {0:0>42b}'.format(integer)
'here is the binary form: 001010101111000001001000111110111111111111'
String Formatting with the new f-strings
Let's demonstrate the new f-strings. They use the same mini-language formatting rules:
>>> integer = 0xABC123EFFF
>>> length = 42
>>> f'{integer:0>{length}b}'
'001010101111000001001000111110111111111111'
Now let's put this functionality into a function to encourage reusability:
def bin_format(integer, length):
return f'{integer:0>{length}b}'
And now:
>>> bin_format(0xABC123EFFF, 42)
'001010101111000001001000111110111111111111'
Aside
If you actually just wanted to encode the data as a string of bytes in memory or on disk, you can use the int.to_bytes method, which is only available in Python 3:
>>> help(int.to_bytes)
to_bytes(...)
int.to_bytes(length, byteorder, *, signed=False) -> bytes
...
And since 42 bits divided by 8 bits per byte equals 6 bytes:
>>> integer.to_bytes(6, 'big')
b'\x00\xab\xc1#\xef\xff'
bin(int("abc123efff", 16))[2:]
>>> bin( 0xABC123EFFF )
'0b1010101111000001001000111110111111111111'
Use Built-in format() function and int() function
It's simple and easy to understand. It's little bit simplified version of Aaron answer
int()
int(string, base)
format()
format(integer, # of bits)
Example
# w/o 0b prefix
>> format(int("ABC123EFFF", 16), "040b")
1010101111000001001000111110111111111111
# with 0b prefix
>> format(int("ABC123EFFF", 16), "#042b")
0b1010101111000001001000111110111111111111
# w/o 0b prefix + 64bit
>> format(int("ABC123EFFF", 16), "064b")
0000000000000000000000001010101111000001001000111110111111111111
See also this answer
"{0:020b}".format(int('ABC123EFFF', 16))
Here's a fairly raw way to do it using bit fiddling to generate the binary strings.
The key bit to understand is:
(n & (1 << i)) and 1
Which will generate either a 0 or 1 if the i'th bit of n is set.
import binascii
def byte_to_binary(n):
return ''.join(str((n & (1 << i)) and 1) for i in reversed(range(8)))
def hex_to_binary(h):
return ''.join(byte_to_binary(ord(b)) for b in binascii.unhexlify(h))
print hex_to_binary('abc123efff')
>>> 1010101111000001001000111110111111111111
Edit: using the "new" ternary operator this:
(n & (1 << i)) and 1
Would become:
1 if n & (1 << i) or 0
(Which TBH I'm not sure how readable that is)
This is a slight touch up to Glen Maynard's solution, which I think is the right way to do it. It just adds the padding element.
def hextobin(self, hexval):
'''
Takes a string representation of hex data with
arbitrary length and converts to string representation
of binary. Includes padding 0s
'''
thelen = len(hexval)*4
binval = bin(int(hexval, 16))[2:]
while ((len(binval)) &lt thelen):
binval = '0' + binval
return binval
Pulled it out of a class. Just take out self, if you're working in a stand-alone script.
I added the calculation for the number of bits to fill to Onedinkenedi's solution. Here is the resulting function:
def hextobin(h):
return bin(int(h, 16))[2:].zfill(len(h) * 4)
Where 16 is the base you're converting from (hexadecimal), and 4 is how many bits you need to represent each digit, or log base 2 of the scale.
Replace each hex digit with the corresponding 4 binary digits:
1 - 0001
2 - 0010
...
a - 1010
b - 1011
...
f - 1111
hex --> decimal then decimal --> binary
#decimal to binary
def d2b(n):
bStr = ''
if n < 0: raise ValueError, "must be a positive integer"
if n == 0: return '0'
while n > 0:
bStr = str(n % 2) + bStr
n = n >> 1
return bStr
#hex to binary
def h2b(hex):
return d2b(int(hex,16))
# Python Program - Convert Hexadecimal to Binary
hexdec = input("Enter Hexadecimal string: ")
print(hexdec," in Binary = ", end="") # end is by default "\n" which prints a new line
for _hex in hexdec:
dec = int(_hex, 16) # 16 means base-16 wich is hexadecimal
print(bin(dec)[2:].rjust(4,"0"), end="") # the [2:] skips 0b, and the
Just use the module coden (note: I am the author of the module)
You can convert haxedecimal to binary there.
Install using pip
pip install coden
Convert
a_hexadecimal_number = "f1ff"
binary_output = coden.hex_to_bin(a_hexadecimal_number)
The converting Keywords are:
hex for hexadeimal
bin for binary
int for decimal
_to_ - the converting keyword for the function
So you can also format:
e. hexadecimal_output = bin_to_hex(a_binary_number)
Another way:
import math
def hextobinary(hex_string):
s = int(hex_string, 16)
num_digits = int(math.ceil(math.log(s) / math.log(2)))
digit_lst = ['0'] * num_digits
idx = num_digits
while s > 0:
idx -= 1
if s % 2 == 1: digit_lst[idx] = '1'
s = s / 2
return ''.join(digit_lst)
print hextobinary('abc123efff')
The binary version of ABC123EFFF is actually 1010101111000001001000111110111111111111
For almost all applications you want the binary version to have a length that is a multiple of 4 with leading padding of 0s.
To get this in Python:
def hex_to_binary( hex_code ):
bin_code = bin( hex_code )[2:]
padding = (4-len(bin_code)%4)%4
return '0'*padding + bin_code
Example 1:
>>> hex_to_binary( 0xABC123EFFF )
'1010101111000001001000111110111111111111'
Example 2:
>>> hex_to_binary( 0x7123 )
'0111000100100011'
Note that this also works in Micropython :)
i have a short snipped hope that helps :-)
input = 'ABC123EFFF'
for index, value in enumerate(input):
print(value)
print(bin(int(value,16)+16)[3:])
string = ''.join([bin(int(x,16)+16)[3:] for y,x in enumerate(input)])
print(string)
first i use your input and enumerate it to get each symbol. then i convert it to binary and trim from 3th position to the end. The trick to get the 0 is to add the max value of the input -> in this case always 16 :-)
the short form ist the join method. Enjoy.
HEX_TO_BINARY_CONVERSION_TABLE = {
'0': '0000',
'1': '0001',
'2': '0010',
'3': '0011',
'4': '0100',
'5': '0101',
'6': '0110',
'7': '0111',
'8': '1000',
'9': '1001',
'a': '1010',
'b': '1011',
'c': '1100',
'd': '1101',
'e': '1110',
'f': '1111'}
def hex_to_binary(hex_string):
binary_string = ""
for character in hex_string:
binary_string += HEX_TO_BINARY_CONVERSION_TABLE[character]
return binary_string
when I time hex_to_binary("123ade")
%timeit hex_to_binary("123ade")
here is the result:
316 ns ± 2.52 ns per loop
Alternatively, you could use "join" method:
def hex_to_binary_join(hex_string):
hex_array=[]
for character in hex_string:
hex_array.append(HEX_TO_BINARY_CONVERSION_TABLE[character])
return "".join(hex_array)
I timed this too:
%timeit hex_to_binary_join("123ade")
397 ns ± 4.64 ns per loop
a = raw_input('hex number\n')
length = len(a)
ab = bin(int(a, 16))[2:]
while len(ab)<(length * 4):
ab = '0' + ab
print ab
import binascii
hexa_input = input('Enter hex String to convert to Binary: ')
pad_bits=len(hexa_input)*4
Integer_output=int(hexa_input,16)
Binary_output= bin(Integer_output)[2:]. zfill(pad_bits)
print(Binary_output)
"""zfill(x) i.e. x no of 0 s to be padded left - Integers will overwrite 0 s
starting from right side but remaining 0 s will display till quantity x
[y:] where y is no of output chars which need to destroy starting from left"""
def conversion():
e=raw_input("enter hexadecimal no.:")
e1=("a","b","c","d","e","f")
e2=(10,11,12,13,14,15)
e3=1
e4=len(e)
e5=()
while e3<=e4:
e5=e5+(e[e3-1],)
e3=e3+1
print e5
e6=1
e8=()
while e6<=e4:
e7=e5[e6-1]
if e7=="A":
e7=10
if e7=="B":
e7=11
if e7=="C":
e7=12
if e7=="D":
e7=13
if e7=="E":
e7=14
if e7=="F":
e7=15
else:
e7=int(e7)
e8=e8+(e7,)
e6=e6+1
print e8
e9=1
e10=len(e8)
e11=()
while e9<=e10:
e12=e8[e9-1]
a1=e12
a2=()
a3=1
while a3<=1:
a4=a1%2
a2=a2+(a4,)
a1=a1/2
if a1<2:
if a1==1:
a2=a2+(1,)
if a1==0:
a2=a2+(0,)
a3=a3+1
a5=len(a2)
a6=1
a7=""
a56=a5
while a6<=a5:
a7=a7+str(a2[a56-1])
a6=a6+1
a56=a56-1
if a5<=3:
if a5==1:
a8="000"
a7=a8+a7
if a5==2:
a8="00"
a7=a8+a7
if a5==3:
a8="0"
a7=a8+a7
else:
a7=a7
print a7,
e9=e9+1
no=raw_input("Enter your number in hexa decimal :")
def convert(a):
if a=="0":
c="0000"
elif a=="1":
c="0001"
elif a=="2":
c="0010"
elif a=="3":
c="0011"
elif a=="4":
c="0100"
elif a=="5":
c="0101"
elif a=="6":
c="0110"
elif a=="7":
c="0111"
elif a=="8":
c="1000"
elif a=="9":
c="1001"
elif a=="A":
c="1010"
elif a=="B":
c="1011"
elif a=="C":
c="1100"
elif a=="D":
c="1101"
elif a=="E":
c="1110"
elif a=="F":
c="1111"
else:
c="invalid"
return c
a=len(no)
b=0
l=""
while b<a:
l=l+convert(no[b])
b+=1
print l

How can I make `bin(30)` return `00011110` instead of `0b11110`? [duplicate]

This question already has answers here:
Python int to binary string?
(36 answers)
Closed 3 years ago.
What does the b stand for in the output of bin(30): 0b11110? Is there any way I can get rid of this b? How can I get the output of bin() to always return a standard 8 digit output?
Using zfill():
Return the numeric string left filled with zeros in a string of length width. A sign prefix is handled correctly. The original string is returned if width is less than len(s).
>>> bin(30)[2:].zfill(8)
'00011110'
>>>
0b is like 0x - it indicates the number is formatted in binary (0x indicates the number is in hex).
See How do you express binary literals in python?
See http://docs.python.org/dev/whatsnew/2.6.html#pep-3127-integer-literal-support-and-syntax
To strip off the 0b it's easiest to use string slicing: bin(30)[2:]
And similarly for format to 8 characters wide:
('00000000'+bin(30)[2:])[-8:]
Alternatively you can use the string formatter (in 2.6+) to do it all in one step:
"{0:08b}".format(30)
Take advantage of the famous format() function with the lesser known second argument and chain it with zfill()
'b' - Binary
'x' - Hex
'o' - Octal
'd' - Decimal
>>> print format(30, 'b')
11110
>>> print format(30, 'b').zfill(8)
00011110
Should do. Here 'b' stands for binary just like 'x', 'o' & 'd' for hexadecimal, octal and decimal respectively.
You can use format in Python 2 or Python 3:
>> print( format(15, '08b') )
00001111
[]'s
You can use this too :
bi=bin(n)[2:]
This will remove the '0b' portion of the returned value and you can use the output anywhere .
The current answers don't consider negative values (thanks #Gui13 for the comment!) in which case you get -0b... instead of just 0b.... You can handle both with a simple if-else where the value is checked whether it's less than zero or not
>>> def printBit(x):
if x < 0:
return '-' + bin(x)[3:].zfill(8) # replace
else:
return bin(x)[2:].zfill(8)
>>> print(printBit(30))
'00011110'
>>> print(printBit(-30))
'-00011110'
or by using replace()
>>> print(bin(30)).replace('0b', '').zfill(8)
The problem with the call above is that one of the bits gets "lost" to the - sign due to the same value being used for the zfill(). You can handle this too with a simple ternary check:
>>> x = 30
>>> print(bin(x)).replace('0b', '').zfill(9 if x < 0 else 8)
'00011110'
>>> x = -30
>>> print(bin(x)).replace('0b', '').zfill(9 if x < 0 else 8)
'-00011110'
Last but not least you can also make the zfill() to automatically adapt the number of 0s to match a byte (8 bits) or a n number of bit quadruplets (4 bits):
>>> def pb(x):
bres = bin(x).replace('0b', '').replace('-', '') # If no minus, second replace doesn't do anything
lres = len(bres) # We need the length to see how many 0s we need to add to get a quadruplets
# We adapt the number of added 0s to get full bit quadruplets.
# The '-' doesn't count since we want to handle it separately from the bit string
bres = bres = ('-' if x < 0 else '') + bres.zfill(lres + (4-lres%4))
return bres
>>> print(pb(7))
'0111'
>>> print(pb(-7))
'-0111'
>>> print(pb(30))
'00011110'
>>> print(pb(-30))
'-00011110'
Here is the final version with adaptable filling of 0s and additional split with space every n characters (where the n is determined by filling factor):
>>> def pb(x, fillingBits=4, splitWithSpace=True):
# If no minus, second replace doesn't do anything
bres = bin(x).replace('0b', '').replace('-', '')
lres = len(bres)
bres = bres.zfill(lres + (fillingBits - (lres % fillingBits)))
lres = len(bres)
# We can also add a blank after every fillingBits character
if splitWithSpace:
bres = ' '.join([bres[i:(i + fillingBits)] for i in range(0, lres, fillingBits)])
bres = ('-' if x < 0 else '') + bres
# We remove any trailing/leading blanks (occurring whenever splitWithSpace enabled)
return bres.strip()
>>> print(pb(7))
'0111'
>>> print(pb(-7))
'-0111'
>>> print(pb(30))
'0001 1110'
>>> print(pb(-30))
'-0001 1110'
python 2.7
print "{0:b}".format(30)
python 3.x
print ('{0:b}'.format(30))

Categories

Resources