Fibonacci Adder Machine - Calculating Digits in Fibonacci Sequence - python

I'm working on a program that will calculate fibonacci numbers with certain digit limitations (i.e. first fibonacci number with 100 digits). The code I have below overall is running, but I am hitting a logical error that has me stumped.
The goal of the code is to calculate Fibonacci numbers in a fashion similar to binary addition. Using an array, each element is to hold a digit from 0 - 9, so each array index represents a 10's place.
It starts working and looping through fine, but it gets off between 13 and 21 because of the way the loop is handled. It adds the number sin the 10's place together and then saves a 31 number.
Is there a way to break out or stop it from adding those together that I'm not seeing?
num1 = [0]*100
num2 = [0]*100
num2[len(num2)-1] = 1
carry = 0
flag = True
while (flag):
#Main for loop to work through the array
for count in range (1, len(num2)):
carry = num2[len(num2) - count] + num1[len(num1) - count]
if carry > 9:
num2[len(num2)- (count + 1)] = num2[len(num2)- (count + 1)] + 1
carry = carry % 10
num1[len(num1) - count] = num2[len(num2) - count]
num2[len(num2) - count] = carry
else:
num1[len(num1) - count] = num2[len(num2) - count]
num2[len(num2) - count] = carry
print(num2)
if num2[0] != 0:
flag = False
Each time it passes the main while loop I'm hoping to see
[0,0,...,0,1]
[0,0,...,0,2]
[0,0,...,0,3]
[0,0,...,0,5]
[0,0,...,0,8]
[0,0,...,1,3]
[0,0,...,2,1]
...
but after it hits the [...,2,1] loop it moves on to [...,3,1]

Here's a bit of a cleaner version of what I believe you're trying to get at.
#Init of Fib variables
a = 0
b = 1
num = 10 #Change this to the number of fib calculation loops.
x = 0
output_arr_len = 100 #Change this to 10 for testing, as it's easier to see.
while x < num:
#Calculate Fib Sequence
c = a + b
a = b
b = c
x += 1
#Output Array
print([0] * (output_arr_len - len(str(c))) + [int(i) for i in str(c)])
Below is the output of the first 20 loops with output_arr_len set to 10.
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 2]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 3]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 5]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 8]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 3]
[0, 0, 0, 0, 0, 0, 0, 0, 2, 1]
[0, 0, 0, 0, 0, 0, 0, 0, 3, 4]
[0, 0, 0, 0, 0, 0, 0, 0, 5, 5]
[0, 0, 0, 0, 0, 0, 0, 0, 8, 9]
[0, 0, 0, 0, 0, 0, 0, 1, 4, 4]
[0, 0, 0, 0, 0, 0, 0, 2, 3, 3]
[0, 0, 0, 0, 0, 0, 0, 3, 7, 7]
[0, 0, 0, 0, 0, 0, 0, 6, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 9, 8, 7]
[0, 0, 0, 0, 0, 0, 1, 5, 9, 7]
[0, 0, 0, 0, 0, 0, 2, 5, 8, 4]
[0, 0, 0, 0, 0, 0, 4, 1, 8, 1]
[0, 0, 0, 0, 0, 0, 6, 7, 6, 5]
[0, 0, 0, 0, 0, 1, 0, 9, 4, 6]

It was even more tricky than in my comments, but this version works correctly:
num1 = [0]*10
num2 = [0]*10
num2[len(num2)-1] = 1
sum = 0
carry = 0
flag = True
while (flag):
#Main for loop to work through the array
for count in range (1, len(num2)):
sum = num2[len(num2) - count] + num1[len(num1) - count] + carry
num1[len(num1) - count] = num2[len(num2) - count]
if sum > 9:
sum = sum % 10
carry = 1
else:
carry = 0
num2[len(num2) - count] = sum
if carry == 1:
num2[0] = num2[0] + 1
print(num2)
if num2[0] != 0:
flag = False
You have also to copy to new1 before applying the carry, even when doing it at the next higher bit...

Here's the corrections to your code. Note that Python has infinite precision integers, so I've added a Fibonacci generator to check the answer.
num1 = [0]*100
num2 = [0]*100
num2[len(num2)-1] = 1
flag = True
# Fibonacci generator for verification of answer
def fib():
a,b = 0,1
while True:
a,b = b,a+b
yield a
# Instance of the generator
f = fib()
# convert a list of single-digit integers to a real integer for display
def value(L):
assert all(n < 10 for n in L) # bug checking for invalid list values.
return int(''.join([str(i) for i in L]))
while (flag):
#Main for loop to work through the array
# Start with zero carry for first digit
carry = 0
for count in range (1,len(num2)+1): # originally off-by-1.
# compute the sum plus the carry of previous sum
temp = num2[len(num2) - count] + num1[len(num1) - count] + carry
# shift num2 digit to num1 digit
num1[len(num1) - count] = num2[len(num2) - count]
# new num2 digit is the one's place of temp sum.
num2[len(num2) - count] = temp % 10
# remember the carry (10's place) for next sum.
carry = temp // 10
# Check for bugs...compare the answer with the next Fibonacci number
assert value(num1) == next(f)
if num1[0] != 0:
flag = False
print(value(num1))
Note you can make the for loop a little simpler by remembering that negative offsets access an array from the end (num2[-1] is the last item in the array) and range can count backwards:
for count in range(-1,-len(num2)-1,-1):
temp = num2[count] + num1[count] + carry
num1[count] = num2[count]
num2[count] = temp % 10
carry = temp // 10 # remember carry for next digit

Related

how to count negative and positive numbers in each set from a list?

I have list which contains 30 numbers
list = [-21,-22,-33,-55,-454,65,48,-516,614,6,2,-64,-64,-87,6,45,87,15,11,03,-34,-6,-68,-959,-653,24,658,68,9,-2181]
Now first I want to count the number of continuous 3 positive or negative numbers. For that I am using this program:
list = [-21,-22,-33,-55,-454,65,48,-516,614,6,2,-64,-64,-87,6,45,87,15,11,03,-34,-6,-68,-959,-653,24,658,68,9,-2181]
counts = []
count = 0
daysCounter = 1
plus_counter = 0
minus_counter = 0
row_counter = 0
answer_counter = 1
for each in list: # for the "dev column"
if each > 0:
minus_counter = 0
plus_counter += 1
if plus_counter == 3:
count = answer_counter
row_counter = answer_counter
counts.append(count)
plus_counter = 0
answer_counter += 1
else:
counts.append(0)
elif each < 0:
plus_counter = 0
minus_counter += 1
if minus_counter == 3:
count = answer_counter
row_counter = answer_counter
counts.append(count)
minus_counter = 0
answer_counter += 1
else:
counts.append(0)
row_counter += 1
print counts
output:
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 0, 0, 7, 0, 0]
This is correct but I want to reset the counter at %10 == 0position. Basically, if the list contains 30 elements then I want to count between 0 to 10th element then 11th to 20th then 21th to 30th element.
desired output:
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0]
Basically, you will have to reset to default values for each period:
# other code
for i, each in enumerate(list): # for the "dev column"
if i % 10 == 0:
count = 0
daysCounter = 1
plus_counter = 0
minus_counter = 0
row_counter = 0
answer_counter = 1
# remaining code
Note: You should not name your list as list, because you override the built-in.
Your question didnt make sense to me, you say you want to reset on every module 10 index, yet you then go on to say in a list of 30 elements you want
0 to 10 (this is 11 elements)
11 to 20 (this is 10 elements)
21 to 30 (this is 10 elements)
The total of this would be 31 elements but you said your list has 30 elements. which would be indexed from 0 to 29. So i have made an assumption here that you do mean every 10 elelemts I.E 0 to 9, 10 to 19, 20 to 29. This makes my output out of line with yours but again i can only make an assumption here that you miscounted with your indexes.
nums = [
-21, -22, -33, -55, -454, 65, 48, -516, 614, 6,
2, -64, -64, -87, 6, 45, 87, 15, 11, 3,
-34, -6, -68, -959, -653, 24, 658, 68, 9, -2181
]
nths = 10
sequential_limit = 3
sequential_count = sequential_finds = 0
indexer = sequential_limit - 1
sequential_list = [0 for _ in range(indexer)]
skip = 0
for index, num in enumerate(nums[indexer:], indexer):
result = 0
if index % nths == 0:
sequential_count = sequential_finds = 0
skip = indexer
if skip:
skip -= 1
else:
negative = sum(1 for next_num in nums[index - indexer:index + 1] if next_num < 0)
positive = sum(1 for next_num in nums[index - indexer:index + 1] if next_num >= 0)
if sequential_limit in (positive, negative):
sequential_finds += 1
sequential_count = 0
skip = indexer
result = sequential_finds
sequential_list.append(result)
print(sequential_list)
OUTPUT
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0]
I think the above desired output you post is not correct
Add this code in the end, This code will reset between 0th to 9th, 10th to 19,20th to 29 elements of a list.
list_len = len(counts)
total_multiple = int(list_len/10)
for i in range(1, total_multiple):
count = 0
for j in range(10*i, 10*i+10):
if(counts[j] > 0):
counts[j] = count
count += 1
print(counts)
It will modify your list and prints
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]

Computing Adjusted Rand Index

I am trying to compute the ARI between two sets of clusters, using this code:
#computes ARI for this type of clustering
def ARI(table,n):
index = 0
sum_a = 0
sum_b = 0
for i in range(len(table)-1):
for j in range(len(table)-1):
sum_a += choose(table[i][len(table)-1],2)
sum_b += choose(table[len(table)-1][j],2)
index += choose(table[i][j],2)
expected_index = (sum_a*sum_b)
expected_index = expected_index/choose(n,2)
max_index = (sum_a+sum_b)
max_index = max_index/2
return (index - expected_index)/(max_index-expected_index)
#choose to compute rand
def choose(n,r):
f = math.factorial
if (n-r)>=0:
return f(n) // f(r) // f(n-r)
else:
return 0
assuming I have created the contingency table correctly, I still get values outside the range of (-1,1).
For instance:
Contingency table:
[1, 0, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 1, 0, 0, 0, 1]
[0, 1, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 1, 1, 2]
[1, 0, 1, 0, 1, 0, 0, 3]
[0, 0, 0, 0, 0, 0, 1, 1]
[3, 1, 1, 1, 1, 1, 2, 0]
yields an ARI of -1.6470588235294115 when I run my code.
Is there a bug in this code?
Also Here is how I am computing the contingency matrix:
table = [[0 for _ in range(len(subjects)+1)]for _ in range(len(subjects)+1)]
#comparing all clusters
for i in range(len(clusters)):
index_count = 0
for subject, orgininsts in orig_clusters.items():
madeinsts = clusters[i].instances
intersect_count = 0
#comparing all instances between the 2 clusters
for orginst in orgininsts:
for madeinst in makeinsts:
if orginst == madeinst:
intersect_count += 1
table[index_count][i] = intersect_count
index_count += 1
for i in range(len(table)-1):
a = 0
b = 0
for j in range(len(table)-1):
a += table[i][j]
b += table[j][i]
table[i][len(table)-1] = a
table[len(table)-1][i] = b
clusters is a list of cluster objects that have attribute instances, which is a list of instances contained in that cluster. orig_clusters is a dictonary with keys representing cluster labels, and values are a list of instances contained in that cluster. Is there a bug in this code?
You make some mistakes calculating the ARI in your code -- you calculate a and b too often because you loop over your table twice instead of just once.
Also, you pass n as a parameter, but apparently it is set to 10 (that is how I get your result). It would be easier to just pass the table and then calculate n from there. I fixed your code a bit:
def ARI(table):
index = 0
sum_a = 0
sum_b = 0
n = sum([sum(subrow) for subrow in table]) #all items summed
for i in range(len(table)):
b_row = 0#this is to hold the col sums
for j in range(len(table)):
index += choose(table[i][j], 2)
b_row += table[j][i]
#outside of j-loop b.c. we want to use a=rowsums, b=colsums
sum_a += choose(sum(table[i]), 2)
sum_b += choose(b_row, 2)
expected_index = (sum_a*sum_b)
expected_index = expected_index/choose(n,2)
max_index = (sum_a+sum_b)
max_index = max_index/2
return (index - expected_index)/(max_index-expected_index)
or if you pass on the table with row- and column sums:
def ARI(table):
index = 0
sum_a = 0
sum_b = 0
n = sum(table[len(table)-1]) + sum([table[i][len(table)-1] for i in range(len(table)-1)])
for i in range(len(table)-1):
sum_a += choose(table[i][len(table)-1],2)
sum_b += choose(table[len(table)-1][i],2)
for j in range(len(table)-1):
index += choose(table[i][j],2)
expected_index = (sum_a*sum_b)
expected_index = expected_index/choose(n,2)
max_index = (sum_a+sum_b)
max_index = max_index/2
return (index - expected_index)/(max_index-expected_index)
then
def choose(n,r):
f = math.factorial
if (n-r)>=0:
return f(n) // f(r) // f(n-r)
else:
return 0
table = [[1, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 1, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 1, 2],
[1, 0, 1, 0, 1, 0, 0, 3],
[0, 0, 0, 0, 0, 0, 1, 1],
[3, 1, 1, 1, 1, 1, 2, 0]]
ARI(table)
ARI(table)
Out[56]: -0.0604008667388949
The correct result!

Data detector for number 1 and 0

I have a data set containing with only 0 and 1. I want to have a detector to find where 1 starts and where 1 ends, and then return something related to their index to a different list each. So I've written some codes as below:
n= [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
def detector (data):
x = 0
start = []
end = []
for index, i in enumerate(data):
if x == 0 and i == 1:
start.append((index+1))
x == 1
elif x == 1 and i==0:
end.append((index))
x == 0
return start, end
print (detector(n))
However when I run the code above, it returned like below, which is not my desired output.
([1, 2, 3, 4, 22, 23, 24, 25, 26, 27, 28, 34, 35, 36, 37, 38], [])
My desired output is as below:
([1, 22, 34], [4,28,38])
As you can see above, the start_time should be[1,22,34] and end_time should be [4,28,38].
If anyone knows how to solve the issue, pls let me know. Appreciated!!
One issue is certainly, that you dont change flag.
== is a comparison operator and does not assign a new value to flag
using enumerate to get positions of 1s and zip to find when sequence of consecutive 1s starts/ends
ones_positions = [position
for position, value in enumerate(n)
if value == 1]
ones_starts = [ones_positions[0]] + [
next_position
for position, next_position in zip(ones_positions,
ones_positions[1:])
if next_position - position > 1]
ones_ends = [position
for position, next_position in zip(ones_positions,
ones_positions[1:])
if next_position - position > 1] + [ones_positions[-1]]
gives us
>>>ones_starts
[0, 21, 33]
>>>ones_ends
[3, 27, 37]
we can specify enumerate's start parameter if you want your indices to start from 1 (when they are naturally start from 0)
ones_positions = [position
for position, value in enumerate(n, start=1)
if value == 1]
after that
>>>ones_starts
[1, 22, 34]
>>>ones_ends
[4, 28, 38]
Finally we can write it as function:
def detector(data, target_value=1):
positions = [position
for position, value in enumerate(data, start=1)
if value == target_value]
start_times = [positions[0]] + [
next_position
for position, next_position in zip(positions,
positions[1:])
if next_position - position > 1]
end_times = [position
for position, next_position in zip(positions,
positions[1:])
if next_position - position > 1] + [positions[-1]]
return start_times, end_times
and test
n = [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
print(detector(n))
gives us
([1, 22, 34], [4, 28, 38])
n = [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
prev_num = 0
starts = []
ends = []
result = (starts, ends)
for idx, num in enumerate(n):
if prev_num == 0 and num == 1:
starts.append(idx + 1)
elif prev_num == 1 and num == 0:
ends.append(idx + 1)
elif num == 1 and idx == (len(n) - 1):
ends.append(idx + 1)
prev_num = num
print(result)
Which prints:
[[1, 22, 34], [5, 29, 38]]
Since #DanielChristiany pointed you where your mistake was. I will present you my solution which is faster than any of presented(at least that works correctly):
edges = (index for index, i in enumerate(n[1:], 1) if i != n[index-1])
if n[0] == 1:
edges = (1, *edges)
if n[-1] == 1:
some = (*edges, len(n))
print(edges[::2], edges[1::2])
Basically it firstly searches edges where element changes from 0 to 1 or from 1 to 0. Then checks if first and last elements are 1 and then print result.
This solution also uses less memory since it uses generators.
You could also try using groupby:
import itertools
L = [[y[0] for y in it]
for x,it in
itertools.groupby(enumerate(n),lambda x: x[1])
][::2]
res = [x[0] for x in L],[x[-1] for x in L]
You could probably arrive at an even more correct solution without using indexes.
Thanks to vishes_shell for the correction

Why does the other list change as well? [duplicate]

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 7 years ago.
I have already solved problem 5 of Project Euler (What is the smallest positive number that is evenly divisible (with no remainder) by all of the numbers from 1 to 20?), but I want to find a faster way (currently 0.000109195709229 seconds).
I tried a dynamic approach, but when I run the code below (it is just the first part) I don't understand why d[var][counter] gets +1 if I explicitly wrote d[i][counter] += 1.
n = 20
d = {1:[0,1] + [0]*19} #a dictionary that assigns to each number a list of its prime factorization
for i in xrange(2,3): #I changed n+1 with 3 for simplicity
var = i
counter = 2
notDone = True
while notDone:
if var % counter == 0:
var /= counter
print var, d[var]
d[i] = d[var] #i has the same prime factorization of var ...
print var, d[var]
d[i][counter] += 1 #... except for 1 number (counter)
print var, d[var] #wtf?
notDone = False
else:
counter += 2 if counter != 2 else 1
This is the outcome:
1 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1 [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
why does this happen?
At the line
d[i] = d[var]
the variable d[i] will hold the same list object as d[var], as lists are mutable.
Instead you need a copy of d[var], that you can get e.g. by
d[i] = d[var][:]

How to convert an integer to a list of bits?

I'm trying to represent an integer as a list of bits and left pad it to 8 bits only if the integer is < 128:
Example input: 0x15
Desired output: [0, 0, 0, 1, 0, 1, 0, 1]
I do it in the following way:
input = 0x15
output = deque([int(i) for i in list(bin(input))[2:]])
while len(output) != 8:
output.appendleft(0)
I would like to convert any integer to a binary-list. Pad to 8 only if the number requires less than 8 bits to represent.
Another Example input: 0x715
Desired output: [1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]
How can I do this both for numbers less then 8 bits and also for larger ones?
For a fixed size of 8 bits:
num = 0x15
out = [1 if num & (1 << (7-n)) else 0 for n in range(8)]
The (1 << (7-n)) creates a single bit mask for a given position, and then bitwise & tests to see if that bit is set in the number. Having n work through 0 to 7 results in all 8 bits in the byte being tested in order.
For arbitrarily sized numbers:
import math
num = 0x715
bits = int(max(8, math.log(num, 2)+1))
out = [1 if num & (1 << (bits-1-n)) else 0 for n in range(bits)]
number = 0x15
output = [int(x) for x in '{:08b}'.format(number)]
'{:08b}'.format(number) represents your number in binary format with 0 padding to 8 digits, then using list comprehension to create a list of bits.
Alternatively, you can use map function:
output = map(int, '{:08b}'.format(0x15))
If you want to use a variable number of bits, here is one way:
width = 8 # 8bit width
output = [int(x) for x in '{:0{size}b}'.format(0x15, size=width)]
output = map(int, '{:0{size}b}'.format(0x15, size=width))
For Python 3, wrap the map(...) call with list() (map returned a list in Python 2 but returns an iterator in 3).
>>> [int(n) for n in bin(0x15)[2:].zfill(8)]
[0, 0, 0, 1, 0, 1, 0, 1]
The slice [2:] is to remove 0b prefix, zfill(8) is to pad zeros on the left.
Solution
Works for any number of bits, faster than the accepted
answer and the current
highest voted answer:
num = 0xAAAA
bit_list = [(num >> shift_ind) & 1
for shift_ind in range(num.bit_length())] # little endian
bit_list.reverse() # big endian
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
Timings
from timeit import timeit
def accepted_answer(number):
output = [int(x) for x in '{:08b}'.format(number)]
return output
def highest_voted_answer(num):
out = [1 if num & (1 << (7-n)) else 0 for n in range(8)]
return out
def this_answer(num):
bit_list = [(num >> shift_ind) & 1
for shift_ind in range(num.bit_length())] # little endian
bit_list.reverse() # big endian
return bit_list
NUM = 0x15
ITERATIONS = int(1e7)
print(timeit(lambda: accepted_answer(NUM), number=ITERATIONS))
print(timeit(lambda: highest_voted_answer(NUM), number=ITERATIONS))
print(timeit(lambda: this_answer(NUM), number=ITERATIONS))
9.884788331000891
9.262861715000327
6.484631327999523
It's easy to do this with format strings
>>> "{:08b}".format(0x15)
'00010101'
>>> "{:08b}".format(0x151)
'101010001'
>>> "{:08b}".format(0x1511)
'1010100010001'
to convert to a list
>>> [1 if x=='1' else 0 for x in "{:08b}".format(0x15)]
[0, 0, 0, 1, 0, 1, 0, 1]
>>> [1 if x=='1' else 0 for x in "{:08b}".format(0x1511)]
[1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]
It's likely to be faster using bit twiddling as in #Amber's answer, but then you'll have to check for special cases and end up with quite a bit of code. If utmost performance isn't required, it's safer to build on what you know already works
np.unpackbits(np.frombuffer(number, np.dtype('B')))
You can shift the number x steps to the right and then make a bitwise and the result with 1 to get the bit at position x, do this with list-comprehension and you get your list. If you need to support negative numbers we may need to add a leading zero to the list to ensure that positive numbers doesn't start with a 1:
import math
def bits(n):
# The number of bits we need to represent the number
num_bits = max(8, int(math.log(abs(n), 2)) + 1)
# The bit representation of the number
bits = [ (n >> i) & 1 for i in range(num_bits) ]
bits.reverse()
# Do we need a leading zero?
if n < 0 or bits[0] == 0:
return bits
return [0] + bits
# Examples
for n in (-0x15, 0x15, 128, 255, 256, -256):
print("{: 4} = {}".format(n, bits(n)))
-21 = [1, 1, 1, 0, 1, 0, 1, 1]
21 = [0, 0, 0, 1, 0, 1, 0, 1]
128 = [0, 1, 0, 0, 0, 0, 0, 0, 0]
255 = [0, 1, 1, 1, 1, 1, 1, 1, 1]
256 = [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
-256 = [1, 0, 0, 0, 0, 0, 0, 0, 0]
from math import ceil
input = 0x15
bin_string = bin(input)[2:]
binary = map(int,bin_string.zfill(int(ceil(len(bin_string)/8.0)*8)))
print(binary)
This will round to nearest multiple of 8 , if u want to round to multiple of 8 only if <128, use a simple if else statement and remove zfill in else
Output for 0x15:
[0, 0, 0, 1, 0, 1, 0, 1]
Output for 0x715:
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]
If you only want to add zeros if less than 128, use this:
input = 0x715
bin_string = bin(input)[2:]
num_bits = (8 if input < 128 else 0)
binary = map(int,bin_string.zfill(num_bits))
print(binary)
Ouput for 0x15:
[0, 0, 0, 1, 0, 1, 0, 1]
Output for 0x715:
[1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1]
I use bitmasks far less than I used to, but when I do use them I often have the need to decompose a value into its parts
def get_Bits(number):
i = 1
list_of_hex = []
while (i <= number):
if ((number & i) > 0):
bitRepresentation = hex(i)
list_of_hex.append(bitRepresentation)
i = i*2
return list_of_hex
you can change the (hex) function to (bin) if you need the binary decomposition

Categories