How to fix bit length when doing bitshift right? - python

I have generated x = 0 - 2047 in hexadecimal (0 - 7ff).
Then, I tried to shift one bit to right, but I want to keep all the value.
for example, for x = 2047 = h7ff.
I want to shift this value to right. can I set fixed bit length, so that even if I shift, it will not cut the 8?
tried:
x = 2047
hex(x)='0x7ff'
hex(x >> 1)='0x3ff'
expecting:
0x3ff8

If you want to add extra digit only if a bit in the result will be chopped off, you can use a simple modulo. Check if the last bit in the value is a 1, and if it is, multiply the number by 0x10 or decimal 16 to add the extra padding. Then bit shift as normal.
hex((x * 0x10 if x % 2 == 1 else x) >> 1)
adding this to a method for reuse:
def rotate(x):
return (x * 0x10 if x % 2 == 1 else x) >> 1
print(hex(x := 0x7ff))
print(hex(x := rotate(x)))
print(hex(x := rotate(x)))
print(hex(x := rotate(x)))
print(hex(x := rotate(x)))
0x7ff
0x3ff8
0x1ffc
0xffe
0x7ff

Related

Parity of integer with arbitrary bits in python

Lot of solutions suggest using xor with right shift, as described here
https://www.geeksforgeeks.org/finding-the-parity-of-a-number-efficiently/
def findParity(x):
x = x ^ (x >> 16);
x = x ^ (x >> 8);
x = x ^ (x >> 4);
x = x ^ (x >> 2);
x = x ^ (x >> 1);
return x & 1;
But they assume 32 or 64 bit or some 2^n bits integer. In python integer could have any number of bits. For instance i = 7, has only 3 bits.
i = 7
print(len(bin(i)) - 2)
Any suggestions on how to calculate parity using xor and right shift for arbitrary number of bits ?
You can use a loop to dynamically change the length of the parity check:
def parity(num):
length = math.ceil(math.log2(math.ceil(math.log2(num)+1)))
for i in range(length-1, -1, -1):
print(2**i)
num^=(num >> (2**i))
return num&1
You will need to use log twice because you first have to find the length of the number then you need log that many operations.

Python function doing with `&` operator

I got a code like this:
def f(x):
return 1 if x & (x-1) == 0 else 0
print(f(20))
Can anyone explain what this function is doing?
i need to understand x & x-1 meaning.
First up, go and have a look at this answer to see how bitwise operators work. Once, you understand that, just be aware that the expression x & x-1 (with unsigned x, at least) will give you zero if and only if x is a power of two or zero (I consider zero to be a special case simply because zero and'ed with anything gives you zero).
The reason x & (x - 1) gives you zero for a power of two is because a power of two takes the binary form on the first line below (a single 1 bit followed by zero or more 0 bits) and subtracting one from it gives you the second form (with the bits all inverted from that single 1 bit onward):
10000000 = 128 (128)
01111111 = 127 (64 + 32 + 16 + 8 + 4 + 2 + 1)
-------- AND
00000000
So, if you and them, all bits become zero. Note that no non-power-of-two other than zero has this property, for example 42:
00101010 = 42 (32 + 8 + 2)
00101001 = 41 (32 + 8 + 1)
-------- AND
00101000 = 40 (32 + 8)

bitwise operation and Two's complement in python

I have an array of (short) data which is shifted 4 to left and it is also a signed number. I need to plot it around zero.
for instance: if the number in the array is 0b0000000011111111 and I shift it to left by 4, I will get 0b000000001111. it is fine.
for instance: if the number in the array is 0b100011111111 and I shift it to left by 4, I will get 0b000010001111. It is fine, but now it is not a negative number.
can someone help ?
You have to write your own implementation of the arithmetic right shift of a 16-bit value, if this is what you need. I suggest you this one, very easy to understand:
def arithmetic_right_shift_on_16_bits(val, n):
# Get the sign bit
s = val & 0x8000
# Perform the shifts, padding with the sign bit
for _ in range(n):
val >>= 1
val |= s
return val
a = arithmetic_right_shift_on_16_bits(0b0000000011111111, 4)
print(bin(a)) # 0b1111
b = arithmetic_right_shift_on_16_bits(0b1000000011111111, 4)
print(bin(b)) # 0b1111100000001111
This does not happen in Python:
>>> bin(0b0000000011111111 >> 4) # 15
'0b1111'
>>> bin(0b100011111111 >> 4) # 143
'0b10001111'
BTW, the number you show as an example of a negative short integer is not one, because you gave only 12 bits. So I will assume that the number of interest is 0b1000000011111111. As Python does not use 2's complement, it is shown as 33023. But you can do the 2's complement by hand: for a short int (16 bits), you just substract 0x10000 to the number.
You can then write:
def short_signed_right_shift(x, i):
if x < 0 or x >= 0x10000: raise ValueError # only accept 16 bits numbers
return x >> i if (x < 0x7FFF) else 0x10000 + ((x - 0x10000) >> i)
You can then use it:
>>> bin(short_signed_right_shift(0b0000000011111111, 4))
'0b1111'
>>> bin(short_signed_right_shift(0b1000000011111111, 4))
'0b1111100000001111'

Print a large integer in Python

I'd like to print an large integer without the "e+XX" at the end in Python.
For example, when I write:
n = 100
k = 18
result = 1
i = 0
while i < k:
result = result * (n - i) / (i + 1)
i += 1
The result is 3.066451080298821e+19, and I would like to have 30664510802988208300.
If you want an integer, you have to use integer division, // instead of /, as mentioned in #farsil's deleted answer.
result = 1
k = 18
n = 100
for i in range(k):
result = result * (n - i) // (i + 1)
print(result)
This only gives the correct result if i + 1 is always a divisor of result * (n - i). However, this is always true, so we are fine.
You cannot use / because that will perform floating-point division, which will truncate the results to 56 bits. The correct result does not fit in 56 bits:
In [1]: int(float(30664510802988208300))
Out[1]: 30664510802988208128
# ^^^ oops... off by 172
Why is floor division safe?
In this case, when the division by 2 is performed, we have multiplied result by n and n-1, at least one of which is a multiple of 2. When i+1 is 3, then we have multiplied by n, n-1, and n-2, at least one of which is a multiple of 3. This pattern works for all numbers.
I think the question you really want to ask is 'how can I print a number in Python without scientific notation?'
The answer is, your number right now is a float. Try print(type(result)) and you will see it says float. You could type cast it to an integer by doing int(result), and it will show close to the full number, 30664510802988208128. It will be a bit off because of the memory size storage limitations of int vs float.
The better way to do this would be like:
result = 1
i = 0
while i < 18:
result = result * (100 - i) // (i + 1)
i += 1
print(result)
which will keep result as an int type. It now should print 30664510802988208300

Python >>= help for decimal to binary function

Hello I was writing a decimal to binary function and I found this code that works perfectly:
while n > 0:
b = str(n % 2) + b
n >>= 1
However I do not know what >>= does could you enlighten me?
Many thanks
It's a binary right shift operation. The bits in n are shifted to the right by 1. It's equivalent of saying n = n >> 1.
From BitwiseOperators in python:
x >> y:
Returns x with the bits shifted to the right by y places. This is the same as //'ing x by 2**y.
For instance, assume an integer 4 and let's shift it to the right by 1 places.
# First let's look at what 4 is in binary.
>>> bin(4)[2:].zfill(8) # this pads to 8 bits.
'00000100'
# If you shift all the bits towards the right 1 places the result is
# '00000010', which in turn is 2 in base 10.
>>> 4 >> 1
2
>>> bin(2)[2:].zfill(8)
'00000010'
it's right shift operation. One bit right is equivalent to divide by 2.

Categories