What is the best way to check if all bits are 1? - python

I thought this would be easy due to ~, but ~ just returns a negative value of 2^x rather than 0.

You can modify a standard bithack for checking if a number is a power of 2 (numbers one less than a power of 2 are all 1s), with a special case check for zero:
def allOnes(n):
return ((n+1) & n == 0) and (n!=0)
print allOnes(255)
print allOnes(158)
print allOnes(0)
print allOnes(-1)
print allOnes(-2)
Output:
True
False
False
True
False

The easiest way would be to check if 0 present in bin(n). Here are some examples:
Number having all 1's:
>>> n=15
>>> bin(n)
'0b1111'
>>> bin(n)[2:]
'1111'
>>> '0' in bin(n)[2:]
False
Number having 1 or more 0's:
>>> n=5
>>> bin(n)
'0b101'
>>> bin(n)[2:]
'101'
>>> '0' in bin(n)[2:]
True

Most of the languages used MSB (most significant bit) as signed value bit. For example 00000001 in binary is 1 in decimal and 10000011 in binary as -125 in decimal (because of MSB is 1 (-128) & 00000011 is 3 in decimal (-128 + 3 = -125)).
Therefore a binary number whose all bits are 1 is equivalent to -1 in decimal.
So simply if the byte_value is a signed integer,
if(byte_value = -1)
{
printf("All One's");
}
else
{
printf("All Not One's");
}
Otherwise
if(byte_value = 255)
{
printf("All One's");
}
else
{
printf("All Not One's");
}

What you probably want is the XOR (^) operator, and not the bitwise NOT (~) operator you tried (since that just reverts every bit). Since you mentioned the ~ operator as your initial approach, I assume you want to find out if all bits are 1 in an integer by comparing with an integer with all 1's. Perhaps you are optimising for speed.
The XOR operator will return a 1 only when either of the bits in the operands are 1. Consequently, it will give a 1 wherever any of the bits are 0.
>>> 100 ^ 000
100
>>> 100 ^ 100
0
>>> 111 ^ 101
10
>>> 111 ^ 111
0
(As you see the resulting integer is not left padded, but it doesn't matter for our purposes.)
The only 'gotcha' is that you need to know the amount of bits in your number in advance.
Then you could check if all bits in it are 1's, by seeing if the resulting number is anything above 0. If it is, then you know not all bits are 1.
Example:
someNumberWithThreeBits ^ 111 == 0 will return True whenever all bits in someNumberWithThreeBits are 1, and false otherwise.
PS: Please note that 000 ^ 000 would also return 0. But you won't encounter that in this case, unless you decide to compare against 000 instead of 111.

Building on #samgak's answer in response to #Martjin Pieters's comment about specific integer sizes, if the requirement is that all bits for a specific size are 1, then our test needs to be modified. Imagine, for example, that we want to test that a nibble-sized integer is all 1 in binary representation:
In [2]: def all_ones_nibble(to_test: int) -> bool:
...: assert 0 <= to_test < (1 << 4)
...: # bin(1 << 4) == "0b10000", therefore bin((1 << 4) - 1) == "0b1111"
...: return to_test == (1 << 4) - 1
...:
In [3]: all_ones_nibble(int("0", base=2))
Out[3]: False
In [4]: all_ones_nibble(int("1", base=2))
Out[4]: False
In [5]: all_ones_nibble(int("1111", base=2))
Out[5]: True
Of course, it's a bit silly to limit ourselves to nibbles, so let's generalize to arbitrary sizes:
In [6]: def all_ones_for_size(to_test: int, size: int) -> bool:
...: return to_test == (1 << size) - 1
...:
In [7]: all_ones_for_size(int("1111", base=2), 4)
Out[7]: True
In [8]: all_ones_for_size(int("11111111", base=2), 8)
Out[8]: True
In [9]: all_ones_for_size(int("11111110", base=2), 8)
Out[9]: False
Finally, just for fun, let's use #riteshtch's technique to achieve the same result:
In [10]: def all_ones_for_size_using_strs(to_test: int, size: int) -> bool:
...: # NOTE: using a format string obviates the need to shave off "0b".
...: # For example, f"{int('1111', base=2):b}" == "1111", whereas
...: # bin(int("1111", base=2)) == "0b1111"
...: as_bin_str = f"{to_test:b}"
...: return len(as_bin_str) == size and not "0" in as_bin_str
...:
In [11]: all_ones_for_size_using_strs(int("11111110", base=2), 8)
Out[11]: False
In [12]: all_ones_for_size_using_strs(int("11111111", base=2), 8)
Out[12]: True
In [13]: all_ones_for_size_using_strs(int("1111", base=2), 8)
Out[13]: False
Note that this answer uses python 3 with type annotations, which will not work with python 2.7, but as python 2 has long-since been sunsetted, hopeful future viewers will find the modern code more useful.

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.

Perfect Numbers and Mersenne Primes - Python

I've written a program which works out the even perfect numbers for all Mersenne Primes from 1-1000, by using ((2^n)-1)(2^(n-1)) where n is a Mersenne Prime number.
This is the program:
def PrimeFinder(PotPrime):
PlaceNum=1
for x in range (int(PotPrime**0.5)):
PlaceNum=PlaceNum+1
if int(PotPrime/PlaceNum) == (PotPrime/PlaceNum):
return False
return True
TrialNum = 1
for x in range (1000):
if PrimeFinder(TrialNum) == True:
if PrimeFinder((2**TrialNum)-1) == True:
print(TrialNum,"is the Mersenne Prime for the perfect number:",(2**(TrialNum-1))*((2**TrialNum)-1))
TrialNum = TrialNum+1
This program works fine, up until somewhere where 32 < TrialNum < 60, as it correctly identifies that 31 is a Mersenne Prime, however it does not for 61 (and all numbers greater than it).
I was wondering if Python simply cannot do calculations that large, or whether there is a flaw in either my understanding Mersenne Primes or programming.
Rounding errors I suppose: if you debug you notice it thinks 2 is a divisor of 2^61 -1 (which makes no sense).
If you replace if int(PotPrime/PlaceNum) == (PotPrime/PlaceNum): with
if PotPrime % PlaceNum == 0: it's fixed. But your algorithm is quite inefficient and 2^61 - 1 is a very large number so expect it to take hours. (probably even longer)
Python's integers do not have limits on their size, so you should arrange your calculations so they're all integer-based. Here are a few changes that could be made in your program to use integers instead of floating-point.
Instead of
for x in range (int(PotPrime**0.5)):
use something like
while x*x < PotPrime:
Instead of
if int(PotPrime/PlaceNum) == (PotPrime/PlaceNum):
use the simpler
if PotPrime % PlaceNum == 0:
Use the Lucas-Lehmer primality test to check what primes produce Mersenne primes (Mp), that way you avoid check the primality of the Mersenne number itself because they are pretty big, and because only prime exponent produce Mp, with this test you only need that that p to be prime and pass this test, then you can build your perfect number as ((2^p)-1)(2^(p-1)).
With this test I can find the first 16 p [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203] that produce a Mp en 12seg in my machine that is kind of old, a Pentium Dual-Core of 3GHz
Here is the code (in python 3.3) you can also use a more powerful primality Test like the Miller-Rabin test or the Baillie-PSW those unlike trial division wound't take forever to check large numbers.
def primality_Test_Trial_Division(n:int) -> bool:
if n >= 0 :
if n<2:
return False
elif n<4:
return True
elif not n&1 or n%3==0:
return False
else:
mid = 1 + int( n**0.5 )
i = 5
while i<mid and n%i:
i += 2
return i>=mid
else:
raise ValueError
isPrime = primality_Test_Trial_Division
def primality_Test_LL(p:int) -> bool:
"""Lucas–Lehmer primality test. Check if Mp = 2^p − 1 is prime.
en.wikipedia.org/wiki/Lucas%E2%80%93Lehmer_primality_test"""
if isPrime(p):
if p==2:
return True
mersenne = (2**p)-1 #Mp
s = 4
for x in range( p-2 ):
s = pow(s,2,mersenne)-2
#Performing the mod Mp at each iteration ensures
#that all intermediate results are at most p bits
#(otherwise the number of bits would double each iteration).
#The same strategy is used in modular exponentiation.
return s==0
else:
return False
import itertools
def perfect_numbers(n:int):
"""print the first n perfect numbers"""
perfect = 0
for p in itertools.count(2):
if primality_Test_LL(p):
print(p,"is the Mersenne Prime for the perfect number:",(2**(p-1))*((2**p)-1))
perfect += 1
if perfect >= n:
break
Perfect Numbers have the following form, they are divisible by the
same number of 2's as the bit_length of the odd factor, which is prime.
semi perfect numbers like 120 and 2016, have this same form, except that
the odd factor is not prime. For example, the factors of 496 are:
[2, 2, 2, 2, 31], and 2k-1 says that 2 * (2 * 2 * 2 * 2)-1 should equal 31. It does,
so 496 just needs a final lucas lehmer test on 31 to test for a final test.
It is very easy to break up an even number to an odd number that you use for
prime testing and an even number that you use for bit_length testing on perfect
numbers, and that is the second example shown below. it's very easy to do.
For example, 496 has the factors and following properties:
import gmpy2
# If you don't have p2ecm, you can use any
# factorization method, but p2ecm is not needed for the final program below
# the example, we use it here just to show the factors.
def isoneminuspowersoftwo(N):
N=N+1
return (N & (N-1) == 0) and N != 0
In [2]: p2ecm(496) # from https://github.com/oppressionslayer/primalitytest
Out[2]: [2, 2, 2, 2, 31]
In [3]: 2*2*2*2
Out[3]: 16
In [5]: isoneminuspowersoftwo(31)
Out[5]: True
In [7]: (2*2*2*2).bit_length() == (31).bit_length()
Out[7]: True
#and
In [8]: 2*(2*2*2*2) -1 # 2k-1
Out[8]: 31
# Perform Lucas Lehmer test on 31 above:
In [106]: s=4
...: for x in range((31).bit_length()-1):
...: s = (s * s - 2) % 31
...: if s in [0,2]: print(True)
...:
True
# All three tests above passed, so the number 496 is a perfect number.
2nd Example
A Simple way to get the factors without factors is using a simple
python program to extract the numbers, which you can than test with:
def ffs(x):
return (x&-x).bit_length()-1
def extractoddfactor(N):
return N//(2**ffs(N))
In [13]: extractoddfactor(496)
Out[13]: 31
In [14]: 496//31
Out[14]: 16
A semiperfect example is below for (2 ** 5)*(2 ** 6-1). It fails on the prime
test so is semiperfect and not a perfect number, althought it passes the
first two tests.
In [11]: (2**5)*(2**6-1)
Out[11]: 2016
In [21]: extractoddfactor(2016)
Out[21]: 63
In [23]: 2016//63
Out[23]: 32
In [24]: (32).bit_length() == (63).bit_length()
Out[24]: True
In [25]: 2*(32) -1 == 63 # 2k-1 test
Out[25]: True
In [107]: s=4
...: for x in range((63).bit_length()-1):
...: s = (s * s - 2) % 63
...: if s in [0,2]: print(True)
...:
# No output, so False
I wrote a program that finds perfect numbers with the above tests
and the above LucasLehmer prime test. If you don't have gmpy2,
just remove the gmpy2.mpz wrappers and change the gmpy2
gmpy2.bit_length(x) statements to pythons equivelant like so:
x.bit_length(). I used gmpy2 as it's ten time faster than without it,
but it's not needed, and can be easily modified to not use it.
This program performs the tests above to test if a number is perfect
or not. It tests for the features of a perfect num, listed above,
and then finishes with a lucas lehmer test.
No external libraries are needed if you remove the gmpy2 mpz wrappers
and change the bit_length() statements to python format
import gmpy2
def ffs(x):
x=gmpy2.mpz(x)
return gmpy2.bit_length(x&-x)-1
def levelx(N, withstats=False):
if N <= 1: return False
N = gmpy2.mpz(N)
zero, one, two = gmpy2.mpz(0), gmpy2.mpz(1), gmpy2.mpz(2)
temp = gmpy2.mpz(N)
newlevel = gmpy2.bit_length(temp)
primetest = gmpy2.mpz(temp//(two**(ffs(temp))))
offset = gmpy2.mpz(temp//primetest)
s = gmpy2.mpz(4)
nextlevel = newlevel // two
check = temp // (two**nextlevel)
prevtemp = two**nextlevel
if withstats == True:
print (newlevel, newlevel, temp)
print (newlevel, nextlevel+one, prevtemp)
if (prevtemp & (prevtemp-one) == zero) and prevtemp != zero:
if gmpy2.bit_length(offset) == gmpy2.bit_length(primetest):
if ((primetest+one) & ((primetest+one)-one) == zero):
for x in range(gmpy2.bit_length(primetest)-1):
s = (s * s - 2) % primetest
if withstats == True:
print(s)
if s in [0,2]: return True
return False
else: return False
else: return False
else: return False
In [69]: levelx((2**4)*(2**5-1))
Out[69]: True
In [101]: for x in range(1, 10000):
...: if levelx((2**x)*(2**(x+1)-1)) == True:
...: print(x+1, (2**x)*(2**(x+1)-1))
...:
2 6
3 28
5 496
7 8128
13 33550336
17 8589869056
19 137438691328
31 2305843008139952128
61 2658455991569831744654692615953842176
89 191561942608236107294793378084303638130997321548169216
107 13164036458569648337239753460458722910223472318386943117783728128
127 14474011154664524427946373126085988481573677491474835889066354349131199152128
...

Get the bit number that differs between two (binary) numbers

I have two numbers (binary or not, does not play any role) which differ in just one bit, e.g. (pseudocode)
a = 11111111
b = 11011111
I want a simple python function that returns the bit position that differs ('5' in the given example, when seen from right to left). My solution would be (python)
math.log(abs(a-b))/math.log(2)
but I wonder if there is a more elegant way to do this (without using floats etc.).
Thanks
Alex
You could use the binary exclusive:
a = 0b11111111
b = 0b11011111
diff = a^b # 0b100000
diff.bit_length()-1 # 5 (the first position (backwards) which differs, 0 if a==b )
unless i am missing something...
this should work:
>>> def find_bit(a,b):
a = a[::-1]
b = b[::-1]
for i in xrange(len(a)):
if a[i] != b[i]:
return i
return None
>>> a = "11111111"
>>> b = "11011111"
>>> find_bit(a,b)
5
maybe not so elegant, but its easy to understand, and it gets the job done.
Without using bitwise operations you could do something like this:
In [1]: def difbit(a, b):
...: if a == b: return None
...: i = 0
...: while a%2 == b%2:
...: i += 1
...: a //= 2
...: b //= 2
...: return i
...:
In [2]: difbit(0b11111111, 0b11011111)
Out[2]: 5
Using (a^b).bit_length()-1 is perfect for numbers which have only one difference bit. EX:
a = 1000000
b = 1000001
(a^b).bit_length()-1
Output: 0
But for numbers which have multiple difference bits, it gives the index of left most difference bit. EX:
a = 111111111111111111111111111111
b = 111111110111011111111111111111
c = a^b # 1000100000000000000000
c.bit_length()-1
Output: 21 # Instead of 17. 21 is the left most difference bit
So to solve this problem we need to isolate the right most set bit and then get its index. Thus, using ((a^b) & (-(a^b))).bit_length()-1 works best for all inputs:
c = (a^b) & (-(a^b)) # 100000000000000000 - Isolates the rightmost set bit
c.bit_length()-1
Output: 17
(a^b) & (-(a^b))).bit_length()-1
Output: 17
Learn about isolating right most set bit from here

Python: Extracting bits from a byte

I'm reading a binary file in python and the documentation for the file format says:
Flag (in binary)Meaning
1 nnn nnnn Indicates that there is one data byte to follow
that is to be duplicated nnn nnnn (127 maximum)
times.
0 nnn nnnn Indicates that there are nnn nnnn bytes of image
data to follow (127 bytes maximum) and that
there are no duplications.
n 000 0000 End of line field. Indicates the end of a line
record. The value of n may be either zero or one.
Note that the end of line field is required and
that it is reflected in the length of line record
field mentioned above.
When reading the file I'm expecting the byte I'm at to return 1 nnn nnnn where the nnn nnnn part should be 50.
I've been able to do this using the following:
flag = byte >> 7
numbytes = int(bin(byte)[3:], 2)
But the numbytes calculation feels like a cheap workaround.
Can I do more bit math to accomplish the calculation of numbytes?
How would you approach this?
The classic approach of checking whether a bit is set, is to use binary "and" operator, i.e.
x = 10 # 1010 in binary
if x & 0b10: # explicitly: x & 0b0010 != 0
print('First bit is set')
To check, whether n^th bit is set, use the power of two, or better bit shifting
def is_set(x, n):
return x & 2 ** n != 0
# a more bitwise- and performance-friendly version:
return x & 1 << n != 0
is_set(10, 1) # 1 i.e. first bit - as the count starts at 0-th bit
>>> True
You can strip off the leading bit using a mask ANDed with a byte from file. That will leave you with the value of the remaining bits:
mask = 0b01111111
byte_from_file = 0b10101010
value = mask & byte_from_file
print bin(value)
>> 0b101010
print value
>> 42
I find the binary numbers easier to understand than hex when doing bit-masking.
EDIT: Slightly more complete example for your use case:
LEADING_BIT_MASK = 0b10000000
VALUE_MASK = 0b01111111
values = [0b10101010, 0b01010101, 0b0000000, 0b10000000]
for v in values:
value = v & VALUE_MASK
has_leading_bit = v & LEADING_BIT_MASK
if value == 0:
print "EOL"
elif has_leading_bit:
print "leading one", value
elif not has_leading_bit:
print "leading zero", value
If I read your description correctly:
if (byte & 0x80) != 0:
num_bytes = byte & 0x7F
there you go:
class ControlWord(object):
"""Helper class to deal with control words.
Bit setting and checking methods are implemented.
"""
def __init__(self, value = 0):
self.value = int(value)
def set_bit(self, bit):
self.value |= bit
def check_bit(self, bit):
return self.value & bit != 0
def clear_bit(self, bit):
self.value &= ~bit
Instead of int(bin(byte)[3:], 2), you could simply use: int(bin(byte>>1),2)
not sure I got you correctly, but if I did, this should do the trick:
>>> x = 154 #just an example
>>> flag = x >> 1
>>> flag
1
>>> nb = x & 127
>>> nb
26
You can do it like this:
def GetVal(b):
# mask off the most significant bit, see if it's set
flag = b & 0x80 == 0x80
# then look at the lower 7 bits in the byte.
count = b & 0x7f
# return a tuple indicating the state of the high bit, and the
# remaining integer value without the high bit.
return (flag, count)
>>> testVal = 50 + 0x80
>>> GetVal(testVal)
(True, 50)

Convert base-2 binary number string to int

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

Categories

Resources