Getting a specific group of binary numbers in an Int? - python

If I am trying to get a specific range of bits (in decimal) at a specific range, is the best way to go about this leftshifting to the end index, and then right shifting back to the start index?
#pesudo-code:
def group(aNumber,start, end):
n = aNumber << 32 - n
a = n >> end - start
print(a)

You can do that in python, you're just not using the correct method. When you want to retrieve part of a number, the operation you're trying to accomplish is called masking.
And you do that with a mask: number & 0xF0 will retreive bits 4 to 7 (without moving them).
So (number & 0xF0) >> 4 will retrieve bits 4 to 7, and shift them all the way to the right.
As for the mask, ((1 << end) - 1) - ((1 << start) - 1) should build a correct mask. So...
mask = ((1 << end) - 1) - ((1 << start) - 1)
result = (number & mask) >> start
Actually, since you shift to the right right after, you don't even have to mask out the bits below those you want, so this will work just as well:
mask = ((1 << end) - 1)
result = (number & mask) >> start

If you want to get from bit b0 a total of bn bits:
def getbits(x, b0, bn):
return (x >> b0) & ((1 << bn) - 1)

Related

Inserting a '0' bit into the middle of a bitsequence in python

This should be fairly simple, but I've yet to see a viable solution.
If I have a bit sequence (represented as an integer), how would I insert a 0 at index n?
For example:
insert(0b100101010101,4) -> 0b1001001010101
insert(0b101,3) -> 0b1010
insert(0b10001,2) -> 0b100001
EDIT: To clarify, I would like to do this without using vectors or strings (only bitwise operators)
You would need to isolate the bits to the left and to the right of the insertion point, then shift the left part one position, and combine both parts again:
def insert(n, bit):
length = n.bit_length()
if bit > length:
raise ValueError("argument out of range")
right = n & ((1 << length - bit) - 1)
return ((n - right) << 1) + right

Left shift but replace the shifted bits with ones

In Python the << operator does the following:
Returns x with the bits shifted to the left by y places (and new bits on the right-hand-side are zeros). This is the same as multiplying x by 2**y.
I want to have another version where it fills 1 on the new bits. Is there a built in function for this, if not how do I write it?
Is x = (x << y) | ((1 << y) - 1) what you're looking for?
First, we shift x left y bits:
x = 21
y = 2
bin(x) == 10101 (in binary)
x << y == 1010100
Then, the number ((1 << y) - 1) gives us a number with only the y lowest bits set to 1,
e.g.
1 << 2 == 100
(1 << 2) - 1 == 011
Finally, we or them to get 1010100 | 11 == 1010111.
There's no such function built in, or, for that matter, available in any extension library I know of.
It's pretty easy to do yourself, though. Say the int is n and you want to shift it left by s bits.
First flip all the bits of n (change all 0 bits to 1, and all 1 bits to 0). Then shift left by s. That adds s 0 bits on the right. Then flip the bits again. The new trailing 0 bits are changed to 1 bits, and the original bits of n are restored.
>>> n = 5
>>> bin(n)
'0b101'
>>> ~(~n << 6)
383
>>> bin(_)
'0b101111111'

an easy way to choose bit(s) form a word

Is there an easy way to choose bit(s) form a word ?
I prefer to use with built in library.
For example,
I read the data from binary file (I read 32bit each time because I work with words)
num = 128 (1000 0000 )
I want: num[7:6] = 10 in binary = 2
I did it with ('shift' and 'and') or int(bin(128)[2:][::-1][6:8][::-1],2)
You could use bitwise operators. e.g,
(((1 << 8) - 1) & num) >> 6
In general, for bits a to b (higher bits to lower, 0-indexed),
(((1 << (a+1)) - 1) & num) >> b
Explanation:
Say num is 121 = 0111 1001, and we want bit 4 to bit 2 (0-indexed). i.e, 110 or 6. So a = 4, b = 2.
((1 << (a+1)) - 1) is just 111...a times. Doing & with this helps us pick the last "a" bits. e.g, any number & 11 will pick its last 2 bits. A number & 111 will pick the last 3 and so on.
So ((1 << (a+1)) - 1) & num is just the last a bits of num.
>> b drops the last b bits.
Therefore, together,
(((1 << (a+1)) - 1) & num) >> b has the effect of picking the last a bits from num, then dropping the last b bits. So together, it will return bits in the a to b range

Understanding bit-manipulation function in Python

I'd really need some help understanding this piece of code: as far as I can see it is inserting a value in an array of bytes in the middle of a byte, but, as I need to reimplement this in Javascript, I'd like to fully understand it.
Array = [0] * 256
Bit_Offset = 0
[...]
def AddBits(byte_offset, bit_offset, bits, value):
global Bit_Offset
global Array
for i in range(bits):
if(value & 0x01):
Array[(byte_offset + ((bit_offset + Bit_Offset + i)/ 8))] |= (0x01 << ((bit_offset + Bit_Offset + i) % 8));
value /=2
Bit_Offset += bits
And it's used like this:
AddBits(3, 0, 8, 0xaa)
AddBits(3, 0, 3, 0xbb)
EDIT: Ok, it does insert values at custom offsets in a byte, but it looks like a very poor algorithm to me (a cycle on every bit to insert, really?). There has to be a better way to do it!
I'm not so good at binary math, but I came up with the idea of shifting the value of something like 8 - bit_offset (so that the first bit it's at the correct offset in a byte), then splitting it in parts if it spans multiple bytes and finally ORing it with the byte in the array. Is this correct? How can I implement the splitting part?
I will just go over the bit type operators.
if(value & 0x01):
This checks to see if the least significant bit is a 1 or 0. If it is a zero we don't do anything.
Array[(byte_offset + ((bit_offset + Bit_Offset + i)/ 8))]
Since all values in the array are a single byte, byte_offset is the index of where we are going to OR the bit. Added to byte_offset is an additional offset of bits from the local bit counter and the global bit counter that are then converted to bytes with the division by 8. Finally we get the index of the byte where we are going to put this bit.
((bit_offset + Bit_Offset + i) % 8)
This is calculating the bit position we are going to OR.
|= (0x01 <<
This takes our bit position and shifts a 1 to that position then ORs it with whatever is already there. We know we can use a 1 here, because the if statement will filter any 0's.
value /=2
This effectively does a bit shift to the right putting the next bit into the LSB. (Could be replaced with value >>=1 )
Bit_Offset += bits
At the end we add the bits that we added to the global offset.
What it does
This function takes Array (an array of bytes) and bit wise ORs in a value at the bit position defined by the global bit offset, argument bit offset, and the argument byte offset. The reason it does it one bit at a time is because you can potentially need to set more than one index of Array (try AddBits(3, 4, 8, 0xaa) and see what I mean).
One improvement would be to change the for loop to:
for i in range(bits):
Array[(byte_offset + ((bit_offset + Bit_Offset + i)/ 8))] |= ((value & 1) << ((bit_offset + Bit_Offset + i) % 8));
value >>=1
Edit: You could also do one byte at a time like this
def AddBits2(byte_offset, bit_offset, bits, value):
global Bit_Offset
global Array
# precompute offsets
bit_offset += Bit_Offset
byte_offset += bit_offset / 8
Bit_Offset += bits
# Mask out any extra bits in value and adjust value to align to byte
value = (((1 << bits) - 1) & value) << (bit_offset % 8)
# go through bytes and OR them in one byte at a time
for i in range((bits + 7) / 8) :
Array[byte_offset + i] |= (value & 0xff)
value >>=8

Pseudocode interpretation

How would the following pseudocode translate into Python?
function IntNoise(32-bit integer: x)
x = (x<<13) ^ x;
return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 7fffffff) / 1073741824.0);
end IntNoise function
I'm not sure about the following items: the 32-bit integer: x argument in the IntNoise call ; the <<, and the &7fffffff.
The function is a random number generator from this webpage: Perlin Noise.
Line by line, here are the changes:
function IntNoise(32-bit integer: x)
We don't need to declare the argument type, and prefer not to use CamelCase, so line one is:
def intnoise(x):
The only thing wrong with the next line is the semicolon. Removing it, we get:
x = (x << 13) ^ x
x will be shifted to the left by 13 bits and then the result will be bitwise exclusive-OR-ed with the starting value of x.
On the next line, once again no semicolon, and the 7ffffff needs to be prefixed with 0x, thus:
return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0)
Altogether, this makes:
def intnoise(x):
x = (x << 13) ^ x
return (1.0 - ((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0)
The "32-bit integer" part doesn't, unless you use numpy.int32. Just mask the value to 32 bits when it makes sense.
The "<<" stands.
The "& 7fffffff" Needs to be converted. The "&" stands, but the hexadecimal literal needs a bit: 0x7fffffff.
As a learning exercise - great, but once you've understood it, just use os.urandom(4) for random numbers, or the functions in random for various pseudo-random generators.
From your code what i did understand is, the function IntNoise takes 32-bit integer as an input. the << is left shift operator from what i know. and it shifts the number's bit for 13 times to the left. ^ is exponential. And 7fffffff must be a number in hex format of representation. it is 8 digit number, every digit i.e. f and 7 takes 4 bits. f is value for 15 in hex.

Categories

Resources