Converting an integer to signed 2's complement binary string - python

Right now, as far as I know, all means of conversion from int to binary bit string is for unsigned conversions (bin, format, etc.). Is there a way to quickly convert a given integer into its corresponding 2's complement bitstring (using minimal bits)?
For example, I'd want this function f to output:
f(-4) = '100'
f(5) = '0101'
f(-13) = '10011'
Right now, my implementation is this code here:
def f(x):
"""Convert decimal to two's complement binary string"""
if x < 0:
bs = bin(x)[3:]
bs_pad = zero_pad(bs, roundup(tc_bits(x)))
return bin((int(invert(bs_pad),2) + 1))#negate and add 1
else: #Positive- sign bit 0.
bs = bin(x)[2:]
return "0b" + zero_pad(bs, roundup(tc_bits(x)))
which basically traces each step of the conversion process- zero-padding, negation, adding 1, then converting back to binary (it actually also ensures the bit width is a multiple of four). This was super tedious to write and I'm wondering if Python supports a faster/more code-concise way.

Nothing built in, but this is more concise:
def f(n):
nbits = n.bit_length() + 1
return f"{n & ((1 << nbits) - 1):0{nbits}b}"
Then, e.g.,
>>> f(0)
'0'
>>> f(1)
'01'
>>> f(2)
'010'
>>> f(3)
'011'
>>> f(-1)
'11'
>>> f(-2)
'110'
>>> f(-3)
'101'

Related

Number to 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.

Exact Value after Floating point not rounding up [duplicate]

I want to remove digits from a float to have a fixed number of digits after the dot, like:
1.923328437452 → 1.923
I need to output as a string to another function, not print.
Also I want to ignore the lost digits, not round them.
round(1.923328437452, 3)
See Python's documentation on the standard types. You'll need to scroll down a bit to get to the round function. Essentially the second number says how many decimal places to round it to.
First, the function, for those who just want some copy-and-paste code:
def truncate(f, n):
'''Truncates/pads a float f to n decimal places without rounding'''
s = '{}'.format(f)
if 'e' in s or 'E' in s:
return '{0:.{1}f}'.format(f, n)
i, p, d = s.partition('.')
return '.'.join([i, (d+'0'*n)[:n]])
This is valid in Python 2.7 and 3.1+. For older versions, it's not possible to get the same "intelligent rounding" effect (at least, not without a lot of complicated code), but rounding to 12 decimal places before truncation will work much of the time:
def truncate(f, n):
'''Truncates/pads a float f to n decimal places without rounding'''
s = '%.12f' % f
i, p, d = s.partition('.')
return '.'.join([i, (d+'0'*n)[:n]])
Explanation
The core of the underlying method is to convert the value to a string at full precision and then just chop off everything beyond the desired number of characters. The latter step is easy; it can be done either with string manipulation
i, p, d = s.partition('.')
'.'.join([i, (d+'0'*n)[:n]])
or the decimal module
str(Decimal(s).quantize(Decimal((0, (1,), -n)), rounding=ROUND_DOWN))
The first step, converting to a string, is quite difficult because there are some pairs of floating point literals (i.e. what you write in the source code) which both produce the same binary representation and yet should be truncated differently. For example, consider 0.3 and 0.29999999999999998. If you write 0.3 in a Python program, the compiler encodes it using the IEEE floating-point format into the sequence of bits (assuming a 64-bit float)
0011111111010011001100110011001100110011001100110011001100110011
This is the closest value to 0.3 that can accurately be represented as an IEEE float. But if you write 0.29999999999999998 in a Python program, the compiler translates it into exactly the same value. In one case, you meant it to be truncated (to one digit) as 0.3, whereas in the other case you meant it to be truncated as 0.2, but Python can only give one answer. This is a fundamental limitation of Python, or indeed any programming language without lazy evaluation. The truncation function only has access to the binary value stored in the computer's memory, not the string you actually typed into the source code.1
If you decode the sequence of bits back into a decimal number, again using the IEEE 64-bit floating-point format, you get
0.2999999999999999888977697537484345957637...
so a naive implementation would come up with 0.2 even though that's probably not what you want. For more on floating-point representation error, see the Python tutorial.
It's very rare to be working with a floating-point value that is so close to a round number and yet is intentionally not equal to that round number. So when truncating, it probably makes sense to choose the "nicest" decimal representation out of all that could correspond to the value in memory. Python 2.7 and up (but not 3.0) includes a sophisticated algorithm to do just that, which we can access through the default string formatting operation.
'{}'.format(f)
The only caveat is that this acts like a g format specification, in the sense that it uses exponential notation (1.23e+4) if the number is large or small enough. So the method has to catch this case and handle it differently. There are a few cases where using an f format specification instead causes a problem, such as trying to truncate 3e-10 to 28 digits of precision (it produces 0.0000000002999999999999999980), and I'm not yet sure how best to handle those.
If you actually are working with floats that are very close to round numbers but intentionally not equal to them (like 0.29999999999999998 or 99.959999999999994), this will produce some false positives, i.e. it'll round numbers that you didn't want rounded. In that case the solution is to specify a fixed precision.
'{0:.{1}f}'.format(f, sys.float_info.dig + n + 2)
The number of digits of precision to use here doesn't really matter, it only needs to be large enough to ensure that any rounding performed in the string conversion doesn't "bump up" the value to its nice decimal representation. I think sys.float_info.dig + n + 2 may be enough in all cases, but if not that 2 might have to be increased, and it doesn't hurt to do so.
In earlier versions of Python (up to 2.6, or 3.0), the floating point number formatting was a lot more crude, and would regularly produce things like
>>> 1.1
1.1000000000000001
If this is your situation, if you do want to use "nice" decimal representations for truncation, all you can do (as far as I know) is pick some number of digits, less than the full precision representable by a float, and round the number to that many digits before truncating it. A typical choice is 12,
'%.12f' % f
but you can adjust this to suit the numbers you're using.
1Well... I lied. Technically, you can instruct Python to re-parse its own source code and extract the part corresponding to the first argument you pass to the truncation function. If that argument is a floating-point literal, you can just cut it off a certain number of places after the decimal point and return that. However this strategy doesn't work if the argument is a variable, which makes it fairly useless. The following is presented for entertainment value only:
def trunc_introspect(f, n):
'''Truncates/pads the float f to n decimal places by looking at the caller's source code'''
current_frame = None
caller_frame = None
s = inspect.stack()
try:
current_frame = s[0]
caller_frame = s[1]
gen = tokenize.tokenize(io.BytesIO(caller_frame[4][caller_frame[5]].encode('utf-8')).readline)
for token_type, token_string, _, _, _ in gen:
if token_type == tokenize.NAME and token_string == current_frame[3]:
next(gen) # left parenthesis
token_type, token_string, _, _, _ = next(gen) # float literal
if token_type == tokenize.NUMBER:
try:
cut_point = token_string.index('.') + n + 1
except ValueError: # no decimal in string
return token_string + '.' + '0' * n
else:
if len(token_string) < cut_point:
token_string += '0' * (cut_point - len(token_string))
return token_string[:cut_point]
else:
raise ValueError('Unable to find floating-point literal (this probably means you called {} with a variable)'.format(current_frame[3]))
break
finally:
del s, current_frame, caller_frame
Generalizing this to handle the case where you pass in a variable seems like a lost cause, since you'd have to trace backwards through the program's execution until you find the floating-point literal which gave the variable its value. If there even is one. Most variables will be initialized from user input or mathematical expressions, in which case the binary representation is all there is.
The result of round is a float, so watch out (example is from Python 2.6):
>>> round(1.923328437452, 3)
1.923
>>> round(1.23456, 3)
1.2350000000000001
You will be better off when using a formatted string:
>>> "%.3f" % 1.923328437452
'1.923'
>>> "%.3f" % 1.23456
'1.235'
n = 1.923328437452
str(n)[:4]
At my Python 2.7 prompt:
>>> int(1.923328437452 * 1000)/1000.0
1.923
The truely pythonic way of doing it is
from decimal import *
with localcontext() as ctx:
ctx.rounding = ROUND_DOWN
print Decimal('1.923328437452').quantize(Decimal('0.001'))
or shorter:
from decimal import Decimal as D, ROUND_DOWN
D('1.923328437452').quantize(D('0.001'), rounding=ROUND_DOWN)
Update
Usually the problem is not in truncating floats itself, but in the improper usage of float numbers before rounding.
For example: int(0.7*3*100)/100 == 2.09.
If you are forced to use floats (say, you're accelerating your code with numba), it's better to use cents as "internal representation" of prices: (70*3 == 210) and multiply/divide the inputs/outputs.
Simple python script -
n = 1.923328437452
n = float(int(n * 1000))
n /=1000
def trunc(num, digits):
sp = str(num).split('.')
return '.'.join([sp[0], sp[1][:digits]])
This should work. It should give you the truncation you are looking for.
So many of the answers given for this question are just completely wrong. They either round up floats (rather than truncate) or do not work for all cases.
This is the top Google result when I search for 'Python truncate float', a concept which is really straightforward, and which deserves better answers. I agree with Hatchkins that using the decimal module is the pythonic way of doing this, so I give here a function which I think answers the question correctly, and which works as expected for all cases.
As a side-note, fractional values, in general, cannot be represented exactly by binary floating point variables (see here for a discussion of this), which is why my function returns a string.
from decimal import Decimal, localcontext, ROUND_DOWN
def truncate(number, places):
if not isinstance(places, int):
raise ValueError("Decimal places must be an integer.")
if places < 1:
raise ValueError("Decimal places must be at least 1.")
# If you want to truncate to 0 decimal places, just do int(number).
with localcontext() as context:
context.rounding = ROUND_DOWN
exponent = Decimal(str(10 ** - places))
return Decimal(str(number)).quantize(exponent).to_eng_string()
>>> from math import floor
>>> floor((1.23658945) * 10**4) / 10**4
1.2365
# divide and multiply by 10**number of desired digits
If you fancy some mathemagic, this works for +ve numbers:
>>> v = 1.923328437452
>>> v - v % 1e-3
1.923
I did something like this:
from math import trunc
def truncate(number, decimals=0):
if decimals < 0:
raise ValueError('truncate received an invalid value of decimals ({})'.format(decimals))
elif decimals == 0:
return trunc(number)
else:
factor = float(10**decimals)
return trunc(number*factor)/factor
You can do:
def truncate(f, n):
return math.floor(f * 10 ** n) / 10 ** n
testing:
>>> f=1.923328437452
>>> [truncate(f, n) for n in range(5)]
[1.0, 1.9, 1.92, 1.923, 1.9233]
Just wanted to mention that the old "make round() with floor()" trick of
round(f) = floor(f+0.5)
can be turned around to make floor() from round()
floor(f) = round(f-0.5)
Although both these rules break around negative numbers, so using it is less than ideal:
def trunc(f, n):
if f > 0:
return "%.*f" % (n, (f - 0.5*10**-n))
elif f == 0:
return "%.*f" % (n, f)
elif f < 0:
return "%.*f" % (n, (f + 0.5*10**-n))
def precision(value, precision):
"""
param: value: takes a float
param: precision: int, number of decimal places
returns a float
"""
x = 10.0**precision
num = int(value * x)/ x
return num
precision(1.923328437452, 3)
1.923
Short and easy variant
def truncate_float(value, digits_after_point=2):
pow_10 = 10 ** digits_after_point
return (float(int(value * pow_10))) / pow_10
>>> truncate_float(1.14333, 2)
>>> 1.14
>>> truncate_float(1.14777, 2)
>>> 1.14
>>> truncate_float(1.14777, 4)
>>> 1.1477
When using a pandas df this worked for me
import math
def truncate(number, digits) -> float:
stepper = 10.0 ** digits
return math.trunc(stepper * number) / stepper
df['trunc'] = df['float_val'].apply(lambda x: truncate(x,1))
df['trunc']=df['trunc'].map('{:.1f}'.format)
int(16.5);
this will give an integer value of 16, i.e. trunc, won't be able to specify decimals, but guess you can do that by
import math;
def trunc(invalue, digits):
return int(invalue*math.pow(10,digits))/math.pow(10,digits);
Here is an easy way:
def truncate(num, res=3):
return (floor(num*pow(10, res)+0.5))/pow(10, res)
for num = 1.923328437452, this outputs 1.923
def trunc(f,n):
return ('%.16f' % f)[:(n-16)]
A general and simple function to use:
def truncate_float(number, length):
"""Truncate float numbers, up to the number specified
in length that must be an integer"""
number = number * pow(10, length)
number = int(number)
number = float(number)
number /= pow(10, length)
return number
There is an easy workaround in python 3. Where to cut I defined with an help variable decPlace to make it easy to adapt.
f = 1.12345
decPlace= 4
f_cut = int(f * 10**decPlace) /10**decPlace
Output:
f = 1.1234
Hope it helps.
Most answers are way too complicated in my opinion, how about this?
digits = 2 # Specify how many digits you want
fnum = '122.485221'
truncated_float = float(fnum[:fnum.find('.') + digits + 1])
>>> 122.48
Simply scanning for the index of '.' and truncate as desired (no rounding).
Convert string to float as final step.
Or in your case if you get a float as input and want a string as output:
fnum = str(122.485221) # convert float to string first
truncated_float = fnum[:fnum.find('.') + digits + 1] # string output
I think a better version would be just to find the index of decimal point . and then to take the string slice accordingly:
def truncate(number, n_digits:int=1)->float:
'''
:param number: real number ℝ
:param n_digits: Maximum number of digits after the decimal point after truncation
:return: truncated floating point number with at least one digit after decimal point
'''
decimalIndex = str(number).find('.')
if decimalIndex == -1:
return float(number)
else:
return float(str(number)[:decimalIndex+n_digits+1])
int(1.923328437452 * 1000) / 1000
>>> 1.923
int(1.9239 * 1000) / 1000
>>> 1.923
By multiplying the number by 1000 (10 ^ 3 for 3 digits) we shift the decimal point 3 places to the right and get 1923.3284374520001. When we convert that to an int the fractional part 3284374520001 will be discarded. Then we undo the shifting of the decimal point again by dividing by 1000 which returns 1.923.
use numpy.round
import numpy as np
precision = 3
floats = [1.123123123, 2.321321321321]
new_float = np.round(floats, precision)
Something simple enough to fit in a list-comprehension, with no libraries or other external dependencies. For Python >=3.6, it's very simple to write with f-strings.
The idea is to let the string-conversion do the rounding to one more place than you need and then chop off the last digit.
>>> nout = 3 # desired number of digits in output
>>> [f'{x:.{nout+1}f}'[:-1] for x in [2/3, 4/5, 8/9, 9/8, 5/4, 3/2]]
['0.666', '0.800', '0.888', '1.125', '1.250', '1.500']
Of course, there is rounding happening here (namely for the fourth digit), but rounding at some point is unvoidable. In case the transition between truncation and rounding is relevant, here's a slightly better example:
>>> nacc = 6 # desired accuracy (maximum 15!)
>>> nout = 3 # desired number of digits in output
>>> [f'{x:.{nacc}f}'[:-(nacc-nout)] for x in [2.9999, 2.99999, 2.999999, 2.9999999]]
>>> ['2.999', '2.999', '2.999', '3.000']
Bonus: removing zeros on the right
>>> nout = 3 # desired number of digits in output
>>> [f'{x:.{nout+1}f}'[:-1].rstrip('0') for x in [2/3, 4/5, 8/9, 9/8, 5/4, 3/2]]
['0.666', '0.8', '0.888', '1.125', '1.25', '1.5']
The core idea given here seems to me to be the best approach for this problem.
Unfortunately, it has received less votes while the later answer that has more votes is not complete (as observed in the comments). Hopefully, the implementation below provides a short and complete solution for truncation.
def trunc(num, digits):
l = str(float(num)).split('.')
digits = min(len(l[1]), digits)
return l[0] + '.' + l[1][:digits]
which should take care of all corner cases found here and here.
Am also a python newbie and after making use of some bits and pieces here, I offer my two cents
print str(int(time.time()))+str(datetime.now().microsecond)[:3]
str(int(time.time())) will take the time epoch as int and convert it to string and join with...
str(datetime.now().microsecond)[:3] which returns the microseconds only, convert to string and truncate to first 3 chars
# value value to be truncated
# n number of values after decimal
value = 0.999782
n = 3
float(int(value*1en))*1e-n

16 bit hex into 14 bit signed int python?

I get a 16 bit Hex number (so 4 digits) from a sensor and want to convert it into a signed integer so I can actually use it.
There are plenty of codes on the internet that get the job done, but with this sensor it is a bit more arkward.
In fact, the number has only 14 bit, the first two (from the left) are irrelevant.
I tried to do it (in Python 3) but failed pretty hard.
Any suggestions how to "cut" the first two digits of the number and then make the rest a signed integer?
The Datasheet says, that E002 should be -8190 ane 1FFE should be +8190.
Thanks a lot!
Let's define a conversion function:
>>> def f(x):
... r = int(x, 16)
... return r if r < 2**15 else r - 2**16
...
Now, let's test the function against the values that the datahsheet provided:
>>> f('1FFE')
8190
>>> f('E002')
-8190
The usual convention for signed numbers is that a number is negative if the high bit is set and positive if it isn't. Following this convention, '0000' is zero and 'FFFF' is -1. The issue is that int assumes that a number is positive and we have to correct for that:
For any number equal to or less than 0x7FFF, then high bit is unset and the number is positive. Thus we return r=int(x,16) if r<2**15.
For any number r-int(x,16) that is equal to or greater than 0x8000, we return r - 2**16.
While your sensor may only produce 14-bin data, the manufacturer is following the standard convention for 16-bit integers.
Alternative
Instead of converting x to r and testing the value of r, we can directly test whether the high bit in x is set:
>>> def g(x):
... return int(x, 16) if x[0] in '01234567' else int(x, 16) - 2**16
...
>>> g('1FFE')
8190
>>> g('E002')
-8190
Ignoring the upper bits
Let's suppose that the manufacturer is not following standard conventions and that the upper 2-bits are unreliable. In this case, we can use modulo, %, to remove them and, after adjusting the other constants as appropriate for 14-bit integers, we have:
>>> def h(x):
... r = int(x, 16) % 2**14
... return r if r < 2**13 else r - 2**14
...
>>> h('1FFE')
8190
>>> h('E002')
-8190
There is a general algorithm for sign-extending a two's-complement integer value val whose number of bits is nbits (so that the top-most of those bits is the sign bit).
That algorithm is:
treat the value as a non-negative number, and if needed, mask off additional bits
invert the sign bit, still treating the result as a non-negative number
subtract the numeric value of the sign bit considered as a non-negative number, producing as a result, a signed number.
Expressing this algorithm in Python produces:
from __future__ import print_function
def sext(val, nbits):
assert nbits > 0
signbit = 1 << (nbits - 1)
mask = (1 << nbits) - 1
return ((val & mask) ^ signbit) - signbit
if __name__ == '__main__':
print('sext(0xe002, 14) =', sext(0xe002, 14))
print('sext(0x1ffe, 14) =', sext(0x1ffe, 14))
which when run shows the desired results:
sext(0xe002, 14) = -8190
sext(0x1ffe, 14) = 8190

Python: How to convert a string of zeros and ones to binary [duplicate]

I'd simply like to convert a base-2 binary number string into an int, something like this:
>>> '11111111'.fromBinaryToInt()
255
Is there a way to do this in Python?
You use the built-in int() function, and pass it the base of the input number, i.e. 2 for a binary number:
>>> int('11111111', 2)
255
Here is documentation for Python 2, and for Python 3.
Just type 0b11111111 in python interactive interface:
>>> 0b11111111
255
Another way to do this is by using the bitstring module:
>>> from bitstring import BitArray
>>> b = BitArray(bin='11111111')
>>> b.uint
255
Note that the unsigned integer (uint) is different from the signed integer (int):
>>> b.int
-1
Your question is really asking for the unsigned integer representation; this is an important distinction.
The bitstring module isn't a requirement, but it has lots of performant methods for turning input into and from bits into other forms, as well as manipulating them.
Using int with base is the right way to go. I used to do this before I found int takes base also. It is basically a reduce applied on a list comprehension of the primitive way of converting binary to decimal ( e.g. 110 = 2**0 * 0 + 2 ** 1 * 1 + 2 ** 2 * 1)
add = lambda x,y : x + y
reduce(add, [int(x) * 2 ** y for x, y in zip(list(binstr), range(len(binstr) - 1, -1, -1))])
If you wanna know what is happening behind the scene, then here you go.
class Binary():
def __init__(self, binNumber):
self._binNumber = binNumber
self._binNumber = self._binNumber[::-1]
self._binNumber = list(self._binNumber)
self._x = [1]
self._count = 1
self._change = 2
self._amount = 0
print(self._ToNumber(self._binNumber))
def _ToNumber(self, number):
self._number = number
for i in range (1, len (self._number)):
self._total = self._count * self._change
self._count = self._total
self._x.append(self._count)
self._deep = zip(self._number, self._x)
for self._k, self._v in self._deep:
if self._k == '1':
self._amount += self._v
return self._amount
mo = Binary('101111110')
Here's another concise way to do it not mentioned in any of the above answers:
>>> eval('0b' + '11111111')
255
Admittedly, it's probably not very fast, and it's a very very bad idea if the string is coming from something you don't have control over that could be malicious (such as user input), but for completeness' sake, it does work.
A recursive Python implementation:
def int2bin(n):
return int2bin(n >> 1) + [n & 1] if n > 1 else [1]
If you are using python3.6 or later you can use f-string to do the
conversion:
Binary to decimal:
>>> print(f'{0b1011010:#0}')
90
>>> bin_2_decimal = int(f'{0b1011010:#0}')
>>> bin_2_decimal
90
binary to octal hexa and etc.
>>> f'{0b1011010:#o}'
'0o132' # octal
>>> f'{0b1011010:#x}'
'0x5a' # hexadecimal
>>> f'{0b1011010:#0}'
'90' # decimal
Pay attention to 2 piece of information separated by colon.
In this way, you can convert between {binary, octal, hexadecimal, decimal} to {binary, octal, hexadecimal, decimal} by changing right side of colon[:]
:#b -> converts to binary
:#o -> converts to octal
:#x -> converts to hexadecimal
:#0 -> converts to decimal as above example
Try changing left side of colon to have octal/hexadecimal/decimal.
For large matrix (10**5 rows and up) it is better to use a vectorized matmult. Pass in all rows and cols in one shot. It is extremely fast. There is no looping in python here. I originally designed it for converting many binary columns like 0/1 for like 10 different genre columns in MovieLens into a single integer for each example row.
def BitsToIntAFast(bits):
m,n = bits.shape
a = 2**np.arange(n)[::-1] # -1 reverses array of powers of 2 of same length as bits
return bits # a
For the record to go back and forth in basic python3:
a = 10
bin(a)
# '0b1010'
int(bin(a), 2)
# 10
eval(bin(a))
# 10

Python int to binary string?

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.

Categories