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
Related
I am trying to find the fastest way of xor'ing all integers(numerals actually) in a string consecutively. The problem makes me feel that there is an simple and a fast answer I just can't think of. But here what I came up with so far.
Setup:
from operator import xor
a = "123"
Regular loop
val = 0
for i in a:
val = val ^ int(i)
print val
operations.xor with reduce
reduce(xor, map(int, list(a)))
I expected the second one to be faster but when the string grows, the difference is almost none. Is there a faster way ?
Note1: And I would like to know if it is possible using just the integer as 123 instead of the string "123". That would be unlogical because I need a list of integers, however sometimes interesting answers appear from places you never expect.
Edit: Here is the results from the methods suggested so far.
import timeit
setup = """
from operator import xor
a = "124"
b = 124
"""
p1 = """
val = 0
for i in a:
val = val ^ int(i)
val
"""
p2 = """
reduce(xor, map(int, list(a)))
"""
p3 = """
val = 0
for i in xrange(3):
val = val ^ (b % 10)
b /= 10
val
"""
p4 = """
15 & reduce(xor, map(ord, a))
"""
print 1, timeit.timeit(p1, setup=setup, number = 100000)
print 2, timeit.timeit(p2, setup=setup, number = 100000)
print 3, timeit.timeit(p3, setup=setup, number = 100000)
print 4, timeit.timeit(p4, setup=setup, number = 100000)
# Gives
1 0.251768243842
2 0.377706036384
3 0.0885620849347
4 0.140079894386
Please also note that using int(a) instead of b in process 3 makes it slower than 4.
On my (Python 3) system, this rework of the solution runs measureably faster than those shown:
from operator import xor
from functools import reduce
print(15 & reduce(xor, map(ord, a)))
If we know they are all digits, 15 & ord('5') pulls out the bits we need with less overhead than int('5'). And we can delay the logical "and", doing it just once at the end.
To use a number instead of a string, you can do:
b = 31415926535897932384626433832795028841971693993751058209749445923078164
val = 0
while b:
b, modulo = divmod(b, 10)
val ^= modulo
print(val)
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.
Lemme clarify:
What would be the fastest way to get every number with all unique digits between two numbers. For example, 10,000 and 100,000.
Some obvious ones would be 12,345 or 23,456. I'm trying to find a way to gather all of them.
for i in xrange(LOW, HIGH):
str_i = str(i)
...?
Use itertools.permutations:
from itertools import permutations
result = [
a * 10000 + b * 1000 + c * 100 + d * 10 + e
for a, b, c, d, e in permutations(range(10), 5)
if a != 0
]
I used the fact, that:
numbers between 10000 and 100000 have either 5 or 6 digits, but only 6-digit number here does not have unique digits,
itertools.permutations creates all combinations, with all orderings (so both 12345 and 54321 will appear in the result), with given length,
you can do permutations directly on sequence of integers (so no overhead for converting the types),
EDIT:
Thanks for accepting my answer, but here is the data for the others, comparing mentioned results:
>>> from timeit import timeit
>>> stmt1 = '''
a = []
for i in xrange(10000, 100000):
s = str(i)
if len(set(s)) == len(s):
a.append(s)
'''
>>> stmt2 = '''
result = [
int(''.join(digits))
for digits in permutations('0123456789', 5)
if digits[0] != '0'
]
'''
>>> setup2 = 'from itertools import permutations'
>>> stmt3 = '''
result = [
x for x in xrange(10000, 100000)
if len(set(str(x))) == len(str(x))
]
'''
>>> stmt4 = '''
result = [
a * 10000 + b * 1000 + c * 100 + d * 10 + e
for a, b, c, d, e in permutations(range(10), 5)
if a != 0
]
'''
>>> setup4 = setup2
>>> timeit(stmt1, number=100)
7.955858945846558
>>> timeit(stmt2, setup2, number=100)
1.879319190979004
>>> timeit(stmt3, number=100)
8.599710941314697
>>> timeit(stmt4, setup4, number=100)
0.7493319511413574
So, to sum up:
solution no. 1 took 7.96 s,
solution no. 2 (my original solution) took 1.88 s,
solution no. 3 took 8.6 s,
solution no. 4 (my updated solution) took 0.75 s,
Last solution looks around 10x faster than solutions proposed by others.
Note: My solution has some imports that I did not measure. I assumed your imports will happen once, and code will be executed multiple times. If it is not the case, please adapt the tests to your needs.
EDIT #2: I have added another solution, as operating on strings is not even necessary - it can be achieved by having permutations of real integers. I bet this can be speed up even more.
Cheap way to do this:
for i in xrange(LOW, HIGH):
s = str(i)
if len(set(s)) == len(s):
# number has unique digits
This uses a set to collect the unique digits, then checks to see that there are as many unique digits as digits in total.
List comprehension will work a treat here (logic stolen from nneonneo):
[x for x in xrange(LOW,HIGH) if len(set(str(x)))==len(str(x))]
And a timeit for those who are curious:
> python -m timeit '[x for x in xrange(10000,100000) if len(set(str(x)))==len(str(x))]'
10 loops, best of 3: 101 msec per loop
Here is an answer from scratch:
def permute(L, max_len):
allowed = L[:]
results, seq = [], range(max_len)
def helper(d):
if d==0:
results.append(''.join(seq))
else:
for i in xrange(len(L)):
if allowed[i]:
allowed[i]=False
seq[d-1]=L[i]
helper(d-1)
allowed[i]=True
helper(max_len)
return results
A = permute(list("1234567890"), 5)
print A
print len(A)
print all(map(lambda a: len(set(a))==len(a), A))
It perhaps could be further optimized by using an interval representation of the allowed elements, although for n=10, I'm not sure it will make a difference. I could also transform the recursion into a loop, but in this form it is more elegant and clear.
Edit: Here are the timings of the various solutions
2.75808000565 (My solution)
8.22729802132 (Sol 1)
1.97218298912 (Sol 2)
9.659760952 (Sol 3)
0.841020822525 (Sol 4)
no_list=['115432', '555555', '1234567', '5467899', '3456789', '987654', '444444']
rep_list=[]
nonrep_list=[]
for no in no_list:
u=[]
for digit in no:
# print(digit)
if digit not in u:
u.append(digit)
# print(u)
#iF REPEAT IS THERE
if len(no) != len(u):
# print(no)
rep_list.append(no)
#If repeatation is not there
else:
nonrep_list.append(no)
print('Numbers which have no repeatation are=',rep_list)
print('Numbers which have repeatation are=',nonrep_list)
I have a bit of code that I want to run multiple times. That seams trivial but there is a twist: I want to change the code in a specific way between iterations. For example:
A = 1
B = ['+','-','/'.'*','**']
C = []
for x in range(len(B)):
C.append(A{B[x]}100)
print(C)
Now, I know this code doesn't work and it's not a proper Python syntax, but i't just an example of what I'd like the code to do.
Ideally I'd get C as a list where 0th element is 1 + 100, 1st element is 1 - 100, 2nd element is 1 / 100 etc. (N.b.: NOT '1 + 100' string. A result of 1 + 100 calculation - 101). Basically I want the code to change itself between iterations of loop in a defined way.
I do not want to define some lengthy if/elif statement since list B is very, very long.
Edit:
Let me give another example. This one is more relevant to my problem.
A = ['mom','dad','me','you','c']
B = ['a','b','something','nothing','cat']
for x in range(len(A)):
C_{A[x]} = B[x]
I want to end up with 5 new variables so that:
Print(C_mom)
a
Print(C_dad)
b
Print(C_c)
cat
Again, I recognize this is not a proper python syntax and this code doesn't work.
First create a dict where each string '+','*' etc point to it's corresponding method imported from operator module.
Now loop over B and fetch the corresponding method from the ops dict and pass the operands to the method.
>>> from operator import add,sub,mul,div,pow
>>> ops = {'+':add,'-':sub,'/':div, '*':mul,'**':pow}
>>> B = ['+','-','/','*','**']
>>> A = 1
>>> [ops[item](A,100) for item in B]
[101, -99, 0, 100, 1]
Use '/': operator.truediv if you want ops['/'](1,100) to return 0.01 instead of 0.
Update:
Creating dynamic variables in python is not a good idea, you should better use a dict here:
>>> A = [1,2,3,4,5]
>>> B = ['a','b','something','nothing','cat']
>>> c = {x:y for x,y in zip(A,B)}
>>> c[1]
'a'
>>> c[2]
'b'
>>> c[5]
'cat
Use globals() to create dynamic variables(don't use this method):
for x,y in zip(A,B):
globals()['C'+str(x)] =y
...
>>> C1
'a'
>>> C2
'b'
Few blob's have been duplicated in my database(oracle 11g), performed XOR operations on the blob using UTL_RAW.BIT_XOR. After that i wanted to count the number of set bits in the binary string, so wrote the code above.
During a small experiment, i wanted to see what is the hex and the integer value produced and wrote this procedure..
SQL> declare
2
3 vblob1 blob;
4
5 BEGIN
6
7 select leftiriscode INTO vblob1 FROM irisdata WHERE irisid=1;
8
9 dbms_output.put_line(rawtohex(vblob1));
10
11
12 dbms_output.put_line(UTL_RAW.CAST_TO_binary_integer(vblob1));
13
14
15 END;
16 /
OUTPUT: HEXVALUE:
0F0008020003030D030C1D1C3C383C330A3311373724764C54496C0A6B029B84840547A341BBA83D
BB5FB9DE4CDE5EFE96E1FC6169438344D604681D409F9F9F3BC07EE0C4E0C033A23B37791F59F84F
F94E4F664E3072B0229DA09D9F0F1FC600C2E380D6988C198B39517D157E7D66FE675237673D3D28
3A016C01411003343C76740F710F0F4F8FE976E1E882C186D316A63C0C7D7D7D7D397F016101B043
0176C37E767C7E0C7D010C8302C2D3E4F2ACE42F8D3F3F367A46F54285434ABB61BDB53CBF6C7CC0
F4C1C3F349B3F7BEB30E4A0CFE1C85180DC338C2C1C6E7A5CE3104303178724CCC5F451F573F3B24
7F24052000202003291F130F1B0E070C0E0D0F0E0F0B0B07070F1E1B330F27073F3F272E2F2F6F7B
2F2E1F2E4F7EFF7EDF3EBF253F3D2F39BF3D7F7FFED72FF39FE7773DBE9DBFBB3FE7A76E777DF55C
5F5F7ADF7FBD7F6AFE7B7D1FBE7F7F7DD7F63FBFBF2D3B7F7F5F2F7F3D7F7D3B3F3B7FFF4D676F7F
5D9FAD7DD17F7F6F6F0B6F7F3F767F1779364737370F7D3F5F377F2F3D3F7F1F2FE7709FB7BCB77B
0B77CF1DF5BF1F7F3D3E4E7F197F571F7D7E3F7F7F7D7F6F4F75FF6F7ECE2FFF793EFFEDB7BDDD1F
FF3BCE3F7F3FBF3D6C7FFF7F7F4FAF7F6FFFFF8D7777BF3AE30FAEEEEBCF5FEEFEE75FFEACFFDF0F
DFFFF77FFF677F4FFF7F7F1B5F1F5F146F1F1E1B3B1F3F273303170F370E250B
INTEGER VALUE: 15
There was a variance between the hex code and the integer value produced, so used the following python code to check the actual integer value.
print int("0F0008020003030D030C1D1C3C383C330A3311373724764C54496C0A6B029B84840547A341BBA83D
BB5FB9DE4CDE5EFE96E1FC6169438344D604681D409F9F9F3BC07EE0C4E0C033A23B37791F59F84F
F94E4F664E3072B0229DA09D9F0F1FC600C2E380D6988C198B39517D157E7D66FE675237673D3D28
3A016C01411003343C76740F710F0F4F8FE976E1E882C186D316A63C0C7D7D7D7D397F016101B043
0176C37E767C7E0C7D010C8302C2D3E4F2ACE42F8D3F3F367A46F54285434ABB61BDB53CBF6C7CC0
F4C1C3F349B3F7BEB30E4A0CFE1C85180DC338C2C1C6E7A5CE3104303178724CCC5F451F573F3B24
7F24052000202003291F130F1B0E070C0E0D0F0E0F0B0B07070F1E1B330F27073F3F272E2F2F6F7B
2F2E1F2E4F7EFF7EDF3EBF253F3D2F39BF3D7F7FFED72FF39FE7773DBE9DBFBB3FE7A76E777DF55C
5F5F7ADF7FBD7F6AFE7B7D1FBE7F7F7DD7F63FBFBF2D3B7F7F5F2F7F3D7F7D3B3F3B7FFF4D676F7F
5D9FAD7DD17F7F6F6F0B6F7F3F767F1779364737370F7D3F5F377F2F3D3F7F1F2FE7709FB7BCB77B
0B77CF1DF5BF1F7F3D3E4E7F197F571F7D7E3F7F7F7D7F6F4F75FF6F7ECE2FFF793EFFEDB7BDDD1F
FF3BCE3F7F3FBF3D6C7FFF7F7F4FAF7F6FFFFF8D7777BF3AE30FAEEEEBCF5FEEFEE75FFEACFFDF0F
DFFFF77FFF677F4FFF7F7F1B5F1F5F146F1F1E1B3B1F3F273303170F370E250B",16)
Answer:
611951595100708231079693644541095422704525056339295086455197024065285448917042457
942011979060274412229909425184116963447100932992139876977824261789243946528467423
887840013630358158845039770703659333212332565531927875442166643379024991542726916
563271158141698128396823655639931773363878078933197184072343959630467756337300811
165816534945075483141582643531294791665590339000206551162697220540050652439977992
246472159627917169957822698172925680112854091876671868161705785698942483896808137
210721991100755736178634253569843464062494863175653771387230991126430841565373390
924951878267929443498220727531299945275045612499928105876210478958806304156695438
684335624641395635997624911334453040399012259638042898470872203581555352191122920
004010193837249388365999010692555403377045768493630826307316376698443166439386014
145858084176544890282148970436631175577000673079418699845203671050174181808397880
048734270748095682582556024378558289251964544327507321930196203199459115159756564
507340111030285226951393012863778670390172056906403480159339130447254293412506482
027099835944315172972281427649277354815211185293109925602315480350955479477144523
387689192243720928249121486221114300503766209279369960344185651810101969585926336
07333771272398091
To get the set-bit count I have written the following code in C:
int bitsoncount(unsigned x)
{
unsigned int b=0;
if(x > 1)
b=1;
while(x &= (x - 1))
b++;
return b;
}
When I tried the same code in python it did not work. I am new to python through curiosity I'm experimenting, excuse me if am wrong.
def bitsoncount(x):
b=0;
if(x>1):
b=1;
while(x &= (x-1)):
I get an error at the last line, need some help in resolving this and implementing the logic in python :-)
I was interested in checking out the set bits version in python after what i have seen!
Related question: Best algorithm to count the number of set bits in a 32-bit integer?
In Python 3.10+, there is int.bit_count():
>>> 123 .bit_count()
6
Python 2.6 or 3.0:
def bitsoncount(x):
return bin(x).count('1')
Example:
>>> x = 123
>>> bin(x)
'0b1111011'
>>> bitsoncount(x)
6
Or
Matt Howells's answer in Python:
def bitsoncount(i):
assert 0 <= i < 0x100000000
i = i - ((i >> 1) & 0x55555555)
i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
return (((i + (i >> 4) & 0xF0F0F0F) * 0x1010101) & 0xffffffff) >> 24
Starting with Python 3.10 you can use int.bit_count():
x = 826151739
print(x.bit_count()) # 16
what you're looking for is called the Hamming Weight.
in python 2.6/3.0 it can be found rather easily with:
bits = sum( b == '1' for b in bin(x)[2:] )
What version of Python are you using?
First off, Python uses white space not semicolon's, so to start it should look something like this...
def bitsoncount(x):
b=0
while(x > 0):
x &= x - 1
b+=1
return b
The direct translation of your C algorithm is as follows:
def bitsoncount(x):
b = 0
while x > 0:
x &= x - 1
b += 1
return b
Maybe this is what you mean?
def bits_on_count(x):
b = 0
while x != 0:
if x & 1: # Last bit is a 1
b += 1
x >>= 1 # Shift the bits of x right
return b
There's also a way to do it simply in Python 3.0:
def bits_on_count(x):
return sum(c=='1' for c in bin(x))
This uses the fact that bin(x) gives a binary representation of x.
Try this module:
import sys
if sys.maxint < 2**32:
msb2= 2**30
else:
msb2= 2**62
BITS=[-msb2*2] # not converted into long
while msb2:
BITS.append(msb2)
msb2 >>= 1
def bitcount(n):
return sum(1 for b in BITS if b&n)
This should work for machine integers (depending on your OS and the Python version). It won't work for any long.
How do you like this one:
def bitsoncount(x):
b = 0
bit = 1
while bit <= x:
b += int(x & bit > 0)
bit = bit << 1
return b
Basically, you use a test bit that starts right and gets shifted all the way through up to the bit length of your in parameter. For each position the bit & x yields a single bit which is on, or none. Check > 0 and turn the resulting True|False into 1|0 with int(), and add this to the accumulator. Seems to work nicely for longs :-) .
How to count the number of 1-bits starting with Python 3.10: https://docs.python.org/3/library/stdtypes.html#int.bit_count
# int.bit_count()
n = 19
bin(n)
# '0b10011'
n.bit_count() # <-- this is how
# 3
(-n).bit_count()
# 3
Is equivalent to (as per page linked above), but more efficient than:
def bit_count(self):
return bin(self).count("1")