Python: What does >>= do? - python

I'm learning python and I stumbled upon something I don't understand.
For instance:
x = 50
while x:
print(x)
x >>= 1
Outputs:
50
25
12
6
3
1
So I infer that it divides by two and rounds to the left if it's not an integer or something similar.
But when I change it to x >>= 3 for instance the output is:
50
6
Can someone please explain what >>= does?
If so, what are useful applications of this kind of operator.

>>= is the augmented assignment statement for the >> right-shift operator. For immutable types such as int it is exactly the same thing as:
x = x >> 1
right-shifting the bits in x one step to the right.
You can see what it does if you print the binary representation of x first:
>>> x = 50
>>> format(x, '08b')
'00110010'
>>> x >>= 1
>>> format(x, '08b')
'00011001'
>>> x = 50
>>> x >>= 3
>>> format(x, '08b')
'00000110'
>>> x
6
Each shift to the right is equivalent to a floor division by 2; 3 shifts thus is as if x was divided by 2 to the power 3, then floored to an integer.
The complementary operator is the left-shift << operator, multiplying the left-hand integer by 2; it is a binary power-of-two operator:
>>> x = 6
>>> format(x, '08b')
'00000110'
>>> x <<= 3
>>> x
48
>>> format(x, '08b')
'00110000'
Augmented assignment operators can differ in behaviour when applied to mutable types such as a list object, where the operation can take place in-place. For example, listobj += [1, 2, 3] will alter listobj itself, not create a new list object, as if listobj.extend([1, 2, 3]) was called.

This is augmented assignment with the right shift operator.
x >>= 1 is shorthand for x = x >> 1.
x >>= k divides by 2**k (i.e. 2 raised to the k-th power).
Thus, x >>= 3 is the integer division by eight.

It's the binary right shift operator.
For example,
if you have 0100b, and you do: 0100b >> 2, then as a result you will have the number 0001b (you've shifted the one two positions to the right).

Related

Converting an integer to signed 2's complement binary string

Right now, as far as I know, all means of conversion from int to binary bit string is for unsigned conversions (bin, format, etc.). Is there a way to quickly convert a given integer into its corresponding 2's complement bitstring (using minimal bits)?
For example, I'd want this function f to output:
f(-4) = '100'
f(5) = '0101'
f(-13) = '10011'
Right now, my implementation is this code here:
def f(x):
"""Convert decimal to two's complement binary string"""
if x < 0:
bs = bin(x)[3:]
bs_pad = zero_pad(bs, roundup(tc_bits(x)))
return bin((int(invert(bs_pad),2) + 1))#negate and add 1
else: #Positive- sign bit 0.
bs = bin(x)[2:]
return "0b" + zero_pad(bs, roundup(tc_bits(x)))
which basically traces each step of the conversion process- zero-padding, negation, adding 1, then converting back to binary (it actually also ensures the bit width is a multiple of four). This was super tedious to write and I'm wondering if Python supports a faster/more code-concise way.
Nothing built in, but this is more concise:
def f(n):
nbits = n.bit_length() + 1
return f"{n & ((1 << nbits) - 1):0{nbits}b}"
Then, e.g.,
>>> f(0)
'0'
>>> f(1)
'01'
>>> f(2)
'010'
>>> f(3)
'011'
>>> f(-1)
'11'
>>> f(-2)
'110'
>>> f(-3)
'101'

Extracting nth bit in hexadecimal value

Let's say I have a string representing a hexadecimal value such as "0x4", binary represented as 0100. If I want test whether the nth bit is set to 1, and where I count starting from the least significant bit (meaning in this example that only the 3rd bit is 1) how can I do this in the most elegant way?
I doubt the way I am doing is very elegant or efficient.
bits = '{0:08b}'.format(int(0x4, 16))
and then check if str(bits[-3]) is "1"
bits = '{0:08b}'.format(int(0x4, 16))
if str(bits[-3]) == "1":
print "Bit is set to 1"
I'd like a neat way of doing this, e.g. using bitwise operators or shifting.
To test if a bit is set, use the bitwise & on a bit mask of just that bit:
>>> bool(12 & 0b0100)
True
To get a bit mask set at the n-th position, bit-shift a 1 by n-1 positions:
>>> n = 3
>>> 1 << n-1
4
>>> bin(1 << n-1)
'0b100'
Combined, you can directly check whether a specific bit is set:
>>> def bitset(number, n):
... """Test whether ``number`` has the ``n``'th bit set"""
... return bool(number & 1 << n - 1)
...
>>> bitset(0x4, 3)
If your input is a string (instead of generating a string from an integer), use int to convert it:
>>> bitset(int('0x4', 16), 3)
Usually you'd use bitwise operators for that:
if 4 & 1 << n:
print('Bit', n, 'is set')
You could use the bin() function to convert an integer to a binary string:
>>> n = int('0x4', 16)
>>> n
4
>>> bin(n)
'0b100'
>>> bin(n)[-3] == '1'
True
A more efficient way would be to operate on the integer directly using bitwise operators:
>>> bool(n & 1<<2) # shift "1" 2 bits to the left and use bitwise and
True
you can use:
def check_nth_bit(str_hex, nth_bit):
return (int(str_hex, 16) & 2 **(nth_bit - 1)) >> (nth_bit - 1) == 1
print(check_nth_bit('0x4', 3))
print(check_nth_bit('0x4', 1))
output:
True
False

The math calculations behind using (%, //) in python by applying (Decimal(), signed numbers )?

I was trying to understand the math behind calculations using / and // and % operators by doing some trials and found the results are similar to calculator only when using Decimal() but without it the results kinda confusing, i tried to add comments #No Ideato my code to mark the points i don't understand,for example:
in this trial for % operator by applying signed and unsigned number the results and with and without Decimal() the results are :
>>> 9%5 #This result will be the reminder
4
>>> (-9)%5 #No Idea
1
>>> Decimal(9)% Decimal(5) #This result will be the reminder
Decimal('4')
>>> Decimal(-9)% Decimal(5) #The result will be the signed reminder
Decimal('-4')
in this trial for // operator and using signed and unsigned number with and without Decimal() the results are :
>>> 9//5 #int result
1
>>> -9//5 #No Idea
-2
>>> Decimal(9)/Decimal(5) #Same result as using calculator
Decimal('1.8')
>>> Decimal(-9)//Decimal(5) #No Idea
Decimal('-1')
Please consider that this question is not a duplicate and i have done some research to get an answer but i found some answered questions that explain only about // operator using only positive signed numbers and doesn't include information about negative signed numbers or using the Decimal() and doesn't have answer about % operator.
so,It will be helpful if someone knows why the results are different and how they are calculated.
Explanation for the behaviour of integers
From python documentation:
Division of integers yields a float, while floor division of integers
results in an integer; the result is that of mathematical division
with the ‘floor’ function applied to the result.
Therefore, an integer division (//) of negative negative and positive number works as follows:
-9 // 5 == floor(-9 / 5) == floor(-1.8) == -2
The modulo operator is the remainder of the integer division, i.e. x % y = x - x // y * y. In your example:
-9 % 5 == -9 - (-9 // 5 * 5) == (-9) - (-2 * 5) == (-9) - (-10) == 1
The documentation also says:
The modulo operator always yields a result with the same sign as its
second operand (or zero); the absolute value of the result is strictly
smaller than the absolute value of the second operand.
But that comes naturally from the formula above, e.g.:
9 % -5 == 9 - (9 // (-5) * (-5)) == 9 - (-2 * (-5)) == 9 - 10 == -1
decimal.Decimal is different
The documentation explains the difference well:
There are some small differences between arithmetic on Decimal objects
and arithmetic on integers and floats. When the remainder operator %
is applied to Decimal objects, the sign of the result is the sign of
the dividend rather than the sign of the divisor:
>>> (-7) % 4
1
>>> Decimal(-7) % Decimal(4)
Decimal('-3')
The integer division operator // behaves analogously, returning the
integer part of the true quotient (truncating towards zero) rather
than its floor, so as to preserve the usual identity x == (x // y) * y
+ x % y:
>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')
As I understand the question, the OP is asking about the different behavior between Python integers and Decimals. I don't think there is any good reason for it. Both choices are possible, but it is a bit confusing for the user that they differ.
Let's call the numerator n, the denominator d and split the result in the interger result i and the remainder r. This means that
n // d = i
n % d = r
For the operations to make sense, we need
i * d + r == n
For n = -9 and d = 5 we see that this is uphold for both i = -1, r = -4 and for i = -2, r = 1 as can be seen by
(i = -1, r = -4) => -1 * 5 + -4 == -9
(i = -2, r = 1) => -2 * 5 + 1 == -9
Now, in Python integer division is defined as always truncate towards minus infinity (down) and the Decimal implementation has chosen to round towards zero. That means that positive values are truncated/rounded down, whereas negative values are rounded up.
Rounding towards zero is the choice made also made in the C language. However, my personal opinion is that the Python choice is much more sane, specifically coming from a hardware background. And given that this is the choice made in Python, I think it is strange (and bad) that Decimal has chosen to do as in the C language.

simple average returns "incorrect" or not, value

python 2.7:
def median(lista):
lista.sort()
print(lista)
x = len(lista)
if x == 1:
return lista[0]
elif len(lista) % 2 != 0:
return lista[((x-1)/2)]
else:
y = lista[(x / 2) - 1]
z = lista[(x / 2)]
print (y,z)
return (y + z) / 2
print(median([1,6,3,4,2,5]))
displays:
[1, 2, 3, 4, 5, 6]
(3, 4)
3
None
why not 3.5?
thank you!
Just do return sum / 2.0 instead of sum / 2
By default the answer would be an int unless explicitly stated.
The answer from #Nick M provides you the solution, but I'd like to add some explanation.
In Python there are different variable types for numbers, most important being int and float:
type(1)
>>> int
type(1.0)
>>> float
When you operate with integers (variables of type int) you get as result also the type int:
5 / 2
>>> 2
You can mix integers and floats together, where a type coercion happens, and the integers are internally converted to floats, getting a float as result:
5 / 2.0
>>> 2.5
You can also explicitly convert the variable types using the methods int() or float():
int(1.0)
>>> 1
float(1)
>>> 1.0
I hope this helps you for better understanding.
EDIT: official documentation for numeric types in Python 2.7:
https://docs.python.org/2/library/stdtypes.html#numeric-types-int-float-long-complex

Find the division remainder of a number

How could I go about finding the division remainder of a number in Python?
For example:
If the number is 26 and divided number is 7, then the division remainder is 5.
(since 7+7+7=21 and 26-21=5.)
For simple divisibility testing, see How do you check whether a number is divisible by another number?.
you are looking for the modulo operator:
a % b
for example:
>>> 26 % 7
5
Of course, maybe they wanted you to implement it yourself, which wouldn't be too difficult either.
The remainder of a division can be discovered using the operator %:
>>> 26%7
5
In case you need both the quotient and the modulo, there's the builtin divmod function:
>>> seconds= 137
>>> minutes, seconds= divmod(seconds, 60)
26 % 7 (you will get remainder)
26 / 7 (you will get divisor, can be float value)
26 // 7 (you will get divisor, only integer value)
If you want to get quotient and remainder in one line of code (more general usecase), use:
quotient, remainder = divmod(dividend, divisor)
#or
divmod(26, 7)
From Python 3.7, there is a new math.remainder() function:
from math import remainder
print(remainder(26,7))
Output:
-2.0 # not 5
Note, as above, it's not the same as %.
Quoting the documentation:
math.remainder(x, y)
Return the IEEE 754-style remainder of x with
respect to y. For finite x and finite nonzero y, this is the
difference x - n*y, where n is the closest integer to the exact value
of the quotient x / y. If x / y is exactly halfway between two
consecutive integers, the nearest even integer is used for n. The
remainder r = remainder(x, y) thus always satisfies abs(r) <= 0.5 *
abs(y).
Special cases follow IEEE 754: in particular, remainder(x, math.inf)
is x for any finite x, and remainder(x, 0) and remainder(math.inf, x)
raise ValueError for any non-NaN x. If the result of the remainder
operation is zero, that zero will have the same sign as x.
On platforms using IEEE 754 binary floating-point, the result of this
operation is always exactly representable: no rounding error is
introduced.
Issue29962 describes the rationale for creating the new function.
If you want to avoid modulo, you can also use a combination of the four basic operations :)
26 - (26 // 7 * 7) = 5
Use the % instead of the / when you divide. This will return the remainder for you. So in your case
26 % 7 = 5
We can solve this by using modulus operator (%)
26 % 7 = 5;
but
26 / 7 = 3 because it will give quotient but % operator will give remainder.
Modulo would be the correct answer, but if you're doing it manually this should work.
num = input("Enter a number: ")
div = input("Enter a divisor: ")
while num >= div:
num -= div
print num
You can find remainder using modulo operator
Example
a=14
b=10
print(a%b)
It will print 4
If you want the remainder of your division problem, just use the actual remainder rules, just like in mathematics. Granted this won't give you a decimal output.
valone = 8
valtwo = 3
x = valone / valtwo
r = valone - (valtwo * x)
print "Answer: %s with a remainder of %s" % (x, r)
If you want to make this in a calculator format, just substitute valone = 8
with valone = int(input("Value One")). Do the same with valtwo = 3, but different vairables obviously.
Here's an integer version of remainder in Python, which should give the same results as C's "%" operator:
def remainder(n, d):
return (-1 if n < 0 else 1) * (abs(n) % abs(d))
Expected results:
remainder(123, 10) == 3
remainder(123, -10) == 3
remainder(-123, 10) == -3
remainder(-123, -10) == -3
you can define a function and call it remainder with 2 values like rem(number1,number2) that returns number1%number2
then create a while and set it to true then print out two inputs for your function holding number 1 and 2 then print(rem(number1,number2)

Categories