I want to split a number into a sequence of 2^n values.
For example, 80 = 64 16, 123 = 64 32 16 8 2 1
I came up with a naive way of doing this like the following:
nums = []
for d in np.binary_repr(123):
nums = [nn << 1 for nn in nums]
nums.append(int(d))
print(nums)
>>> [64, 32, 16, 8, 0, 2, 1]
I'll probably have to write this in C too. So, I'd like to know more C ways of achieving this (in Python, for the moment)
CodePudding user response:
for (int p= 1; p <= n; p<<= 1) if (p & n) cout << p;
or if you want zeroes,
for (int p= 1; p <= n; p<<= 1) cout << p & n;
The formatting is up to you.
CodePudding user response:
You could write a one-line lambda function to do what you want:
list2n = lambda n: [2**p for p, d in enumerate(bin(n)[:1:-1]) if d == '1']
list2n(123)
list2n(0)
list2n(64)
Output:
[1, 2, 8, 16, 32, 64]
[]
[64]
Note python has a builtin bin
function that does (roughly) the same thing as np.binary_repr
.
CodePudding user response:
you could try something like the following :
l = 123
r= reversed(list(format(l, "b")))
k = list(reversed([int(x)*2**num for num, x in enumerate(r)]))
print(k)
->[64, 32, 16, 8, 0, 2, 1]
which could be also done on one line, but this is for sure not the most efficient way to do it, if this would be the point.
CodePudding user response:
You certainly don't need numpy for something this trivial and you definitely don't want to be converting to/from strings.
def bits(n):
rv = []
b = 1
while b <= n:
rv.insert(0, n & b)
b <<= 1
return rv
print(bits(123))
Output:
[64, 32, 16, 8, 0, 2, 1]
Note:
Might be better to append rather than insert and then reverse the list before returning
CodePudding user response:
One possible way to do it in C :
int p{1};
while (n)
{
if (n & 0x1)
{
std::cout << p;
}
else
{
std::cout << 0;
}
n >>= 1;
p <<= 1;
}