I need to extract some bits from an integer. However how many bits to be extracted is not fixed.
For example a certain code is generating 2 numbers a and b. What I want is a code that could do
c = a[b-1:0]
One of the methods I read about on the web is w say b is a fixed value 3, a simple method to do is
c=bin (a >> 0 & 0b111 )
But this could be done if value of b is fixed 3 i.e we right shift based on known fixed number of bits being anded i.e 3.
But what if the "3" is not fixed? During run time I may need lower 4 bits or 3 bits or 2 bits...anything.
I thing I tried and hoped it would work is
x = bin(a)
c= x[b-1:0]
But even this doesn't work.
Some of your code is trying to access the bits of an integer using slice notation ([:]) but that only works with sequences, not integers.
First you need to decide if you want to work with a string representation of your number in binary, or an integer representation, and be consistent about that. Let's start with a string representation in binary. a is the input number, b is the number of bits.
>>> a = 35
>>> x = bin(a)
>>> x
'0b100011'
Now you want a string representation in binary of the integer that is the rightmost b positions of this string:
>>> b = 3
>>> x[-b:]
'011'
Deprived of its 0b prefix, this string of 3 digits could mean anything. Some examples: in binary, 3; in decimal, 11; in octal 9; in hex, 17. We know from reading the code that it is part of the output from a bin() call, but the string doesn't carry that information around with it. The 3 digits mean whatever you intend them to mean.
If you want to convert that into something you can do arithmetic with, you call int() to convert it back to an integer. But because int() can't tell that the representation is supposed to be binary, do this:
>>> int(x[-b:],2)
3
The 2 passed as the second parameter to int() specifies what base the string is supposed to be in. It's not specifying a conversion: it's specifying an interpretation. It's optional, but if you leave it out then int() will use the default base, which is of course 10.
>>> int(x[-b:])
11
This happens because without any indication of the base, 011 means "eleven, with a leading zero". And int() converts a string to an integer: just integer, not base-10 integer. The internal representation of integer is only converted to base 10 when you ask the interpreter to display it. (Internally, Python integers actually use base 2**30, but most of us never have to think about that much, and I recommend you don't either.)
Now consider just working with integers. If the number of bits you want to mask off is b then (as johnrsharpe points out), you can get the corresponding mask using (2**b - 1):
>>> 2**b - 1
7
Just to demonstrate this is what you actually want:
>>> bin(2**b - 1)
'0b111'
Then you can use the bitwise & operator to get the digits you want. This works sort of opposite to the string method: instead of chopping off the 3 digits that you want, you instead use & to set the digits you don't want to zero:
a = 100011
b = 000111 &
------
000011
Then you can obtain the result directly without having to go through a string conversion and taking slices and converting back to integer:
>>> a & 2**b - 1
3
As you can see this gives the same result in one step. In your question I also see a right shift operator >> but because you are shifting zero positions it does nothing. If you also want to accept a shift quantity, say s, then in the examples above, use (a >> s) instead of a.
From the question, it is not very clear what you actually want to do, but what I understood is that you want to extract 'b' last bits from 'a'.
If two numbers are 'a' and 'b':
First, convert 'a' into binary:
x = bin(a)[2:]
Extracting last b bits from a:
p = x[len(x)-b:]
If you actually want the (lower) bits of the integer value: something like this could do it:
def getbits(value, numbits):
""" Extract the lower numbits of value. """
return value & (2 ** numbits - 1)
value = 0b010011000111
for i in range(value.bit_length()+1):
print('getbits({:012b}, {:2d}): {:12b}'.format(value, i, getbits(value, i)))
Output:
getbits(010011000111, 0): 0
getbits(010011000111, 1): 1
getbits(010011000111, 2): 11
getbits(010011000111, 3): 111
getbits(010011000111, 4): 111
getbits(010011000111, 5): 111
getbits(010011000111, 6): 111
getbits(010011000111, 7): 1000111
getbits(010011000111, 8): 11000111
getbits(010011000111, 9): 11000111
getbits(010011000111, 10): 11000111
getbits(010011000111, 11): 10011000111
Related
I would need to format a python Decimal object to have atleast two decimals, but no more than 5. Is there a reliable way to do this?
Examples:
1.6 --> 1.60
1.678 --> 1.678
1.98765 --> 1.98765
If there are more than two decimals, it is vital that it does not get truncated to only two decimals.
It looks to me like there are two parts to this question - one, determining the correct number of digits and two, quantizing the values to that number of digits.
To do the first, I would get the current exponent using the as_tuple() method. Unless I'm overlooking something simpler.
>>> import decimal
>>> d = decimal.Decimal("1.678")
>>> d.as_tuple().exponent
-3
>>> d2 = decimal.Decimal("1.6")
>>> d2.as_tuple().exponent
-1
So from that you can compute the desired exponent:
MAX_EXPONENT = -2
MIN_EXPONENT = -5
def desired_exponent(d):
current_exponent = d.as_tuple().exponent
return min(MAX_EXPONENT, max(MIN_EXPONENT, current_exponent))
The second is answered by the accepted answer on the marked duplicate - use the quantize() method. You'll need to construct a Decimal value with the desired exponent you can provide as the argument to quantize(). There are multiple ways to do that, but two simple ones are exponentiating decimal.Decimal("10") or using the tuple constructor for decimal.Decimal().
>>> quant_arg = decimal.Decimal("10") ** -2
>>> decimal.Decimal("1.6").quantize(quant_arg)
Decimal('1.60')
Or:
>>> quant_arg = decimal.Decimal((0, (), -2))
>>> decimal.Decimal("1.6").quantize(quant_arg)
Decimal('1.60')
I used -2 as a literal there, you'd want to use the calculated value of desired_exponent.
There are multiple ways to organize this code, I think the parts that are not obvious are a) accessing the current exponent of a decimal value and b) some of the ways of constructing an arg for quantize(). And this is all assuming you need the actual decimal objects, and aren't just outputting them - if this is a question just about output formatting re-quantizing is probably overkill.
Here is the code I use now:
def unitAmount(value):
"""Format a Decimal to match -?[0-9]{1,15}(,[0-9]{2,5})?
Minimum two decimals, max 5.
"""
decimals = value.as_tuple().exponent
if decimals == -1: # For values like 1.6 --> 1.60
value = value.quantize(Decimal('1.00'))
elif decimals < -5: # For values like 1.1234567.. --> 1.12345
value = value.quantize(Decimal('1.00000'))
return value
I am having a hard time trying to figure out why I am getting the result with my code that I am getting.
c = int(format(ord('c'), 'b'))
h = int(format(ord('h'), 'b'))
result = c | h
print(c)
print(h)
print(result)
This returns a result of:
1100011
1101000
1101035
So my question is after the | operation, why is it 1101035 when (according to my understanding) it should be 1101011?
The call to format with the second argument being "b" gives you the binary representation of the number in the first argument. So, if you print it, you will see the "0"s and "1"s.
However, when you use int on this result, withug informing int that your string is base 2, it thinks these are decimal numbers. So, it will "read" the sequence "1100011" (the binary representation of 99, the unicode codepoint for the "c" character), as "1_100_011", or "one million, one hundred thousand and eleven" - and that is the number in your c variable if you print or make any numeric operations with it.
This can be easily solved by telling int that the numeric strings you are reading are binary themselves:
c = int(format(ord('c'), 'b'), 2)
(Passing 2 as the second argument to "int" to indicate the base). If you inspect "c" at this point, it contains the number 99, which will behave as expected with your "|" operator. Of course, if you are not looking at the binary representation of the number, there is no point in generating it to start with, so your code could be just c = ord('c')...
Doing int() here makes no sense (it's taking your string of binary bits and interpreting them as a decimal number). You just want:
c = ord('c')
h = ord('h')
result = c | h
print(format(c, 'b'))
print(format(h, 'b'))
print(format(result, 'b'))
(only using format for display on screen, not for calculation!)
which prints:
1100011
1101000
1101011
I am trying to make a program that converts a given integer(limited by the value 32 bit int can hold) into 32 bit binary number. For example 1 should return (000..31times)1. I have been searching the documents and everything but haven't been able to find some concrete way. I got it working where number of bits are according to the number size but in String. Can anybody tell a more efficient way to go about this?
'{:032b}'.format(n) where n is an integer. If the binary representation is greater than 32 digits it will expand as necessary:
>>> '{:032b}'.format(100)
'00000000000000000000000001100100'
>>> '{:032b}'.format(8589934591)
'111111111111111111111111111111111'
>>> '{:032b}'.format(8589934591 + 1)
'1000000000000000000000000000000000' # N.B. this is 33 digits long
You can just left or right shift integer and convert it to string for display if you need.
>>> 1<<1
2
>>> "{:032b}".format(2)
'00000000000000000000000000000010'
>>>
or if you just need a binary you can consider bin
>>> bin(4)
'0b100'
Say for example the number you want to convert into 32 bit binary is 4. So, num=4.
Here is the code that does this: "s" is the empty string initially.
for i in range(31,-1,-1):
cur=(num>>i) & 1 #(right shift operation on num and i and bitwise AND with 1)
s+=str(cur)
print(s)#s contains 32 bit binary representation of 4(00000000000000000000000000000100)
00000000000000000000000000000100
Lets say
a = 4
print(bin(a)) # 0b101
For the output you may append 0s from LSB to till 101 to get the 32bit address for the integer - 4.
If you don't want 0b you may slice it
print(bin(a)[-3:]) # 101
Say I have a number, 18573628, where each digit represents some kind of flag, and I want to check if the value of the fourth flag is set to 7 or not (which it is).
I do not want to use indexing. I want to in some way and with a flag mask, such as this:
00070000
I would normally use np.logical_and() or something like that, but that will consider any positive value to be True. How can I and while considering the value of a digit? For example, preforming the operation with
flags = 18573628
and
mask = 00070000
would yield 00010000
though trying a different mask, such as
mask = 00040000
would yield 00000000
What you can do is
if (x // 10**n % 10) == y:
...
to check if the n-th digit of x (counting from right) is equal to y
You have to use divide and modulo for a decimal mask:
flags = 18573628
mask = 10000
if (flags / mask) % 10 == 7:
do_something
You can convert the input number into an array of digit numbers and then simply indexing into that array with that specific index or indices would give us those digit(s). For doing that conversion, we can use np.fromstring, like so -
In [87]: nums = np.fromstring(str(18573628),dtype=np.uint8)-48
In [88]: nums
Out[88]: array([1, 8, 5, 7, 3, 6, 2, 8], dtype=uint8)
In [89]: nums[3] == 7
Out[89]: True
Say I have a number, 18573628, where each digit represents some kind of flag, and I want to check if the value of the fourth flag is set to 7
Firstly, bitwise operations like & are bit-wise, which is to say they operate on base-2 digits. They don't operate naturally on digits of any other base, although bases which are themselves powers of 2 work out ok.
To stick with bit-wise operations
You need to know how many values each flag can take, to figure out how many bits each flag needs to encode.
If you want to allow each flag the values zero to nine, you need four bits. However, in this scheme, your number won't behave like a normal integer (storing a base-10 digit in each 4-bit group is called Binary Coded Decimal).
The reason it won't behave like a normal integer is that flag values 1,2,3 will be stored as 1 * 16**2 + 2*16 + 3 instead of the 1 * 10**2 + 2*10 + 3 you'd normally expect. So you'd need to write some code to support this use. However, extracting flag n (counting from zero at the right) just becomes
def bcdFlagValue(bcd, flagnum):
if flagnum == 0:
return bcd & 0x0F;
return 0x0F & (bcd >> ((flagnum-1) * 4))
If you actually need a different range of values for each flag, you need to choose the correct number of bits, and adjust the shift and mask values appropriately.
In either case, you'll need a helper function if you want to print your flags as the base-10 number you showed.
To use normal base 10 numbers
You need to use division and modulo (as 6502 showed), because base-10 numbers don't fit evenly into base-2 bits, so simple bit operations don't work
Note
The BCD approach saves space at the cost of complexity, effort and some speed - from subsequent comments, it's probably simpler to just use the string of digit characters directly unless you really need to save 4 bits per digit.
if flags and mask are hexadecimal values, you can do:
flags = int("18573628", 16)
mask = int("00070000", 16)
result = flags & mask
print(hex(result))
=> '0x70000'
Without dealing with the particulars of your case (the SDSS data, which should be documented in the product specification), let's look at some options.
First, you need to to know if it is to be read in big-endian or little-endian order (is the first bit to the right or to the left). Then you need to know the size of each flag. For a series of yes-no parameters, it could simply be 1 bit (0 or 1). For up to four options, it could be two bits (00, 01, 10, 11), etc. It is also possible that some combinations are reserved for future expansion, don't currently have meaning, and should not be expected to occur in the data. I've also seen instances where the flag size varies, so first n bits mean refer to parameter x, next n bits refer to parameter y, etc.
There is a good explanation of the concept as part of Landsat-8 satellite imagery:
http://landsat.usgs.gov/qualityband.php
To read the values, you convert the base 10 integer to binary, and traverse it in the specified chunks, converting back to int to obtain the parameter values according to your product specification.
I wrote a small script to find n-digit primes in the digits of e (in relation to that old Google ad):
import math
# First 251 digits of e
e_digits = ("2"
"7182818284 5904523536 0287471352 6624977572 4709369995"
"9574966967 6277240766 3035354759 4571382178 5251664274"
"2746639193 2003059921 8174135966 2904357290 0334295260"
"5956307381 3232862794 3490763233 8298807531 9525101901"
"1573834187 9307021540 8914993488 4167509244 7614606680")
e_digits = e_digits.replace(" ", "")
digits = int(raw_input("Number of digits: "))
print "Finding ", str(digits) + "-digit primes in the first", len(e_digits), "digits of e."
numbers = []
primes = []
# Creates list of numbers based on variable digits
for n in range(0,len(e_digits) - (digits - 1)):
test_number = e_digits[n:n+digits]
numbers.append(int(test_number))
# Checks each number for divisors smaller than its sqrt, then appends to list primes
for n in numbers:
n_sqrt = int(math.floor(math.sqrt(n)))
div = []
for i in range(2,n_sqrt+1):
if n % i == 0:
div.append(i)
if div == []:
primes.append(n)
print primes
However, when I set digits = 10, this is printed:
[7427466391L, 7413596629L, 6059563073L, 3490763233L, 2988075319L, 1573834187, 7021540891L, 5408914993L]
All of the list entries except for number six has been concatenated with an "L", and I have no clue why. The problem arises when I run the code in IDLE as well as in CMD, though only when appending ten digit integers using this specific code.
In the if-statement in the last for loop, the correct numbers are printed if I print n, or if I convert n to a string before appending. However, then converting to a integer again creates the same problem.
The problem also occurs with digits = 11, but not with digits < 10.
I cannot for the life of me find the error (or figure out if there is an error at all, really). Some advice on this would be greatly appreciated.
Your code is working just fine and what you see is normal. Those are literal representations of Python long integers.
When printing a list, the contents of a list are printed as representations, the same output as the repr() function would give. The alternative is to print individual elements of the list instead.
You don't need to worry about the long representation, however. That is just an implementation detail of Python integers leaking through:
>>> 1234567890
1234567890
>>> type(1234567890)
<type 'int'>
>>> 12345678901234567890
12345678901234567890L
>>> type(12345678901234567890)
<type 'long'>
Here, the Python interpreter prints the results of expressions as repr() representations too. Integers larger than sys.maxint automatically become long integers.
Quoting the documentation:
Plain integers (also just called integers) are implemented using long in C, which gives them at least 32 bits of precision (sys.maxint is always set to the maximum plain integer value for the current platform, the minimum value is -sys.maxint - 1). Long integers have unlimited precision.
and
Unadorned integer literals (including binary, hex, and octal numbers) yield plain integers unless the value they denote is too large to be represented as a plain integer, in which case they yield a long integer. Integer literals with an 'L' or 'l' suffix yield long integers ('L' is preferred because 1l looks too much like eleven!).
Comparisons and arithmetic between regular and long integers is fully supported and transparent:
Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the “narrower” type is widened to that of the other, where plain integer is narrower than long integer is narrower than floating point is narrower than complex. Comparisons between numbers of mixed type use the same rule.
Python 3 removed the distinction altogether.