Python invert a number - python

First of all I'm not a Python expert, so here is my topic:
I want to invert a number, let say number = "ABCD123" (yes this is a string but I need to do it this way ...), the problem is that I'm not really satisfy with the way Python deal with the inversion, for example ~0xABCD123 is -180146468 and I don't want the MSB but only the "current" bits to be inverted. I can go with something like ~0xABCD123 & 0XFFFFFFF but the size of the number can actually change...
Question
Is there a way to dynamically "cast" or remove the bit sign in Python with the operator ~

A simple hack:
def invert_int(n):
number_bit_len = n.bit_length()
max_val = (2 ** number_bit_len) - 1
return ~n & max_val

Related

Is there a built-in python function to count bit flip in a binary string?

Is there a built-in python function to count bit flip in a binary string? The question I am trying to solve is given a binary string of arbitrary length, how can I return the number of bit flips of the string. For example, the bit flip number of '01101' is 3, and '1110011' is 2, etc.
The way I can come up with to solve this problem is to use a for loop and a counter. However, that seems too lengthy. Is there a way I can do that faster? Or is there a built-in function in python that allows me to do that directly? Thanks for the help!
There is a very fast way to do that without any explicit loops and only using Python builtins: you can convert the string to a binary number, then detect all the bit flips using a XOR-based integer tricks and then convert the integer back to a string to count the number of bit flips. Here is the code:
# Convert the binary string `s` to an integer: "01101" -> 0b01101
n = int(s, 2)
# Build a binary mask to skip the most significant bit of n: 0b01101 -> 0b01111
mask = (1 << (len(s)-1)) - 1
# Check if the ith bit of n is different from the (i+1)th bit of n using a bit-wise XOR:
# 0b01101 & 0b01111 -> 0b1101 (discard the first bit)
# 0b01101 >> 1 -> 0b0110
# 0b1101 ^ 0b0110 -> 0b1011
bitFlips = (n & mask) ^ (n >> 1)
# Convert the integer back to a string and count the bit flips: 0b1011 -> "0b1011" -> 3
flipCount = bin(bitFlips).count('1')
This trick is much faster than other methods since integer operations are very optimized compare to a loop-based interpreted codes or the ones working on iterables. Here are performance results for a string of size 1000 on my machine:
ljdyer's solution: 96 us x1.0
Karl's solution: 39 us x2.5
This solution: 4 us x24.0
If you are working with short bounded strings, then there are even faster ways to count the number of bits set in an integer.
Don't know about a built in function, but here's a one-liner:
bit_flip_count = len([x for x in range(1, len(x0)) if x0[x] != x0[x-1]])
Given a sequence of values, you can find the number of times that the value changes by grouping contiguous values and then counting the groups. There will be one more group than the number of changes (since the elements before the first change are also in a group). (Of course, for an empty sequence, this gives you a result of -1; you may want to handle this case separately.)
Grouping in Python is built-in, via the standard library itertools.groupby. This tool only considers contiguous groups, which is often a drawback (if you want to make a histogram, for example, you have to sort the data first) but in our case is exactly what we want. The overall interface of this tool is a bit complex, but in our case we can use it simply:
from itertools import groupby
def changes_in(sequence):
return len(list(groupby(sequence))) - 1

make calculator by spliting input text in python

guys thanks for having me I've got a question already.
What I wanna do is to get sum of the list without for loop after splitting the given text by math symbols which the text as an example ** (1+3) * 3 ** should obtain the math priority for calculation.
my first question is how to get sum and sub and multiply or divide by the list and then how to check the priority and check it first.
# my calc
a = input()
result = a.split('+')
print(sum(result))
sol1: split brackets and mul /dev earlier sum /sub later but I know that split is not the best way!
sol2: make a tree I don t know what it is lol but mind it
it has answered here I know but with no split
Calculator in python
You could use eval (but be aware that it is usually a bad practice, see this answer):
result = eval(input())
If you input a string like (3-8)*4+5/2, the result will be automatically computed using normal priorities: -17.5.

How to get bit value of hex number based on position in python

Hi Friends I'm new person to Python language. I'm trying to write some small code which I want to integrate later in my python module. Here is my question
I have a number like a[31:0]= 0X00010001 in a file and I want to get bit value based on position and do the operation based on its bit value.
I want to use something like common class across and I'm looking for solution if a number is more than 32 bits as well.
0x00010001.getbit(0) == 0 do some operation. Expecting if bit0 is 0 do operation.
One more I'm looking if I have corresponding mask bit how do I get value based on mask bit
0x00010001 in this case bit[15] is mask and bit[0] is value.
Appreciate help.
I have tried doing via bitstream module but was not successful
For the first problem:
def getbit(x,n):
"Get the n-th bit of the number x"
return x & (1 << n) and 1 or 0
Explanation: x & (1 << n) means bitwise AND between x and 2^n.
And the expression P and 1 or 0 means: if P then return 1, otherwise return 0.
And this works for numbers of any size. Python is not limiting you to 32 bit integers.

Python: Shorten ugly code?

I have a ridiculous code segment in one of my programs right now:
str(len(str(len(var_text)**255)))
Is there an easy way to shorten that? 'Cause, frankly, that's ridiculous.
A option to convert a number >500 digits to scientific notation would also be helpful
(that's what I'm trying to do)
Full code:
print("Useless code rating:" , str(len(var_text)**255)[1] + "e" + str(len(str(len(var_text)**255))))
TL;DR: y = 2.408 * len(var_text)
Lets assume that your passkey is a string of characters with 256 characters available (0-255). Then just as a 16bit number holds 65536 numbers (2**16) the permutations of a string of equal length would be
n_perms = 256**len(passkey)
If you want the number of (decimal) digits in n_perms, consider the logarithm:
>>> from math import log10
>>> log10(1000)
3.0
>>> log10(9999)
3.9999565683801923
>>>
So we have length = floor(log10(n_perms)) + 1. In python, int rounds down anyway, so I'd say you want
n_perms = 256**len(var_text)
length = int(log10(n_perms)) + 1
I'd argue that 'shortening' ugly code isn't always the best way - you want it to be clear what you're doing.
Edit: On further consideration I realised that choosing base-10 to find the length of your permutations is really arbitrary anyway - so why not choose base-256!
length = log256(256**len(var_text)
length = len(var_text) # the log and exp cancel!
You are effectively just finding the length of your passkey in a different base...
Edit 2: Stand back, I'm going to attempt Mathematics!
if x = len(var_text), we want y such that
y = log10(256**x)
10**y = 256**x
10**y = (10**log10(256))**x
10**y = (10**(log10(256)x))
y = log10(256) * x
So, how's this for short:
length = log10(256) * len(var_text) # or about (2.408 * x)
This looks like it's producing a string version of the number of digits in the 255th power of the length of a string. Is that right? I'd be curious what that's used for.
You could compute the number differently, but it's not shorter and I'm not sure it's prettier:
str(int(math.ceil(math.log10(len(var_text))*255)))
or:
"%d" % math.ceil(math.log10(len(v))*255)
Are you trying to determine the number of possible strings having the same length as var_text? If so, you have your base and exponent reversed. You want to use 255**len(var_text) instead of len(var_text)**255.
But, I have to ask ... how long do these passkeys get to be, and what are you using them for?
And, why not just use the length of the passkey as an indicator of its length?
Firstly, if your main problem is manipulating huge floating point expressions, use the bigfloat package:
>>> import bigfloat
>>> bigfloat.BigFloat('1e1000')
BigFloat.exact('1.0000000000000001e+1000', precision=53)
As for the details in your question: len(str(num)) is approximately equal to log(num, 10) + 1. This is not significantly shorter, but it's certainly a better way of expressing it in code (for the benefit of anyone who doesn't know that off the top of their head). You can then simplify it with log laws:
len(str(x**y))
= log(x**y, 10) + 1
= y * log(x, 10) + 1
So maybe you'll find:
"%i" % (log(len(var_text),10)*255 + 1)
... is better? It's not significantly shorter, but it's a much clearer mathematical relationship between input and output.

Best way to overwrite some bits in a particular range

Given a series of bits, what's the best way to overwrite a particular range of them.
For example, given:
0100 1010
Say I want to overwrite the middle 2 bits with 10 to make the result:
0101 0010
What would be the best way of doing this?
At first, I thought I would just shift the overwriting bits I want to the correct position (10000), and then use a bitwise OR. But I realized that while it preserves the other bits, there's no way of specifying which bits I want to actually overwrite.
I was looking into Python's bitarray module, but I just want to double-check that I'm not looking over an extremely simple bitwise operation to do this for me.
Thanks.
This is done by first masking the bits you want to erase (forcing them to zero while preserving the other bits) before applying the bitwise OR.
Use a bitwise AND with the pattern (in this case) 11100111.
If you already have a "positive" version of the pattern (here this would be 00011000), which is easier to generate, you can obtain the "negative" version 11100111 using what is called 1's complement, available as ~ in Python and most languages with a C-like syntax.
a = 0b01001010
a &= 0b11100111
a |= 0b00010000
The and first zeroes the target bits:
01001010
& 11100111
--------
01000010
then the or fills them with the desired data:
01000010
| 00010000
--------
01010010
I see you got excellent answers in the "bit manipulation" vein. If you have to do a lot of this, though, I would still recommend reading the discussion here and links therefrom, and, as that wiki suggests, a few of the packages found this way (BitVector, BitPacket, bitarray) -- readability is important, and experience shows that removing non-obvious inline code from your application-level flow in favor of calls to well-named APIs enhances it.
If you do decide to go with manipulation, automatic generation of the bit-ranges masks given bit-indices is clearly crucial. I would recommend starting with an "atomic bitmask" with just one 1 bit, built by shifting:
>>> bin(1 << 7)
'0b10000000'
as you see, 1 << 7 has a one followed by 7 zeros -- and therefore:
>>> bin((1 << 7) - 1)
'0b1111111'
(1 << 7) - 1 has exactly 7 ones (you need the parentheses because the priority of the shifting operator << is lower than that of the subtraction operator -) as the least significant bits aka LSB (and of course all zeros left of that).
Given an easy way to make "a bitmask with N ones" (as the LSB), making ones with bits N included to M excluded set and all other cleared is easy -- using named functions for extra readability:
>>> def n_lsb(x): return (1 << x) - 1
...
>>> def n_to_m(n, m): return n_lsb(n) & ~ n_lsb(m)
...
>>> bin(n_to_m(7, 3))
'0b1111000'
So, now, to set bits N included to M excluded to a certain pattern, as other answers have shown:
>>> def set_bits(i, n, m, pat): return (i & ~n_to_m(n, m))|(pat<<m)
...
>>> bin(set_bits(511, 7, 3, 0b0101))
'0b110101111'
While this answer does not, per se, allow you to do anything more than the others, I do hope it can help "teach you to fish" (vs. just giving you a fish;-) and thereby help you (and other readers) in the future.
BTW, I would recommend reducing to a minimum the mix of bitwise and arithmetic operations -- in this A the only arithmetic operation I use is that - 1 in n_lsb, a hopefully very clear case; in more general cases, two's complement arithmetic (what ordinary integer arithmetic looks like when looked at from a bitwise point of view) could be tricky.
You can do it in 2 steps:
Create a number with all the 0's you
want to write in that looks like
1111 0111 and use an AND
Create a number with all the 1's
that looks like 0001 0000 and use
an OR
BTW: The first number can easily be created by subtracting a 1 shifted into the position of your zeros from 255. So for example, do 255 - (0000 1000).
a = 255 - (1 << x)
b = 1 << y
result = (source & a) | b
where x and y are the positions of your respective bits.
>>> bin(0b01001010 & 0b11110111 | 0b00010000)
'0b1010010'
This is a small basic set of bitwise functions I made from a couple of answers( Thanks to #Alex Martelli for the great answer).
Just open a new python file call it BITManipulation.py copy this code to it import it from your code and you can access all the functions without any need for working with bits.
Anyway I always suggest to understand how it work deeply.
"""
BitManipulation.py
This file is used to define some basic bit manipulations functions
"""
##func: get_bit
##params: value,n
##return: the N-th bit from value
def get_bit(value, n):
return ((value >> n & 1) != 0)
##func: set_bit
##params: value,n
##return: value with the N-th bit Set to 1
def set_bit(value, n):
return value | (1 << n)
##func: clear_bit
##params: value,n
##return: value with the N-th bit Set to 0
def clear_bit(value, n):
return value & ~(1 << n)
##func: n_lsb
##params: x ( Example 7)
##return: a number with exactly x bits of 1 ( Example 0b1111111 )
def n_lsb(x):
return (1 << x) - 1
##func: n_to_m
##params: n,m (n > m)( Example 5,3 )
##return: a number with bits n -> m set to 1 ( Example 0b00011000 )
def n_to_m(n, m):
return n_lsb(n) & ~ n_lsb(m)
##func: set_bits
##params: x,n,m,pat (n > m)( Example 511,5,3,0b0101 )
##return: sets bits n -> m in x to pat ( Example 0b110101111 )
def set_bits(x, n, m, pat):
return (x & ~n_to_m(n, m))|(pat<<m)

Categories