This question already has answers here:
How does the modulo (%) operator work on negative numbers in Python?
(12 answers)
Closed 4 months ago.
How python calculate mathematically this modulo?
>>>-1%10
9
The Wikipedia article on the modulo operation provides the following constraint for a % q:
a = nq + r
Substituting a = -1, q = 10 and r = 9, we see that n must be equal -1.
Plugging in -1 for n:
-1 % 10 # Python evaluates this as 9
-1 = n * 10 + r
-1 = -1 * 10 + r
9 = r
Testing with another example (again plugging in -1 for n):
-7 % 17 # Python evaluates this as 10
-7 = n * 17 + r
-7 = -17 + r
10 = r
A third example with a positive numerator and negative denominator:
7 % -17 # Python evaluates this as -10
7 = n * (-17) + r
7 = -1 * (-17) + r
7 = 17 + r
-10 = r
It appears that when a and q have different signs, we start with n = -1 and decrement n by 1 until we've found the n closest to zero such that n*q < a. We can test this by trying this out with an a and q such that |a| > |q|:
-100 % 11 # Python evaluates as 10
-100 = n * 11 + r
... -1 # -11 > -100
... -2 # -22 > -100
... -3 ...
... -4 ...
... -5 ...
... -6 ...
... -7 ...
... -8 ...
... -9 # -99 > -100
-100 = -10 * 11 + r # -110 < -100
-100 = -110 + r
10 = r
So while this might not be the algorithm Python actually uses to calculate the modulo, we at least have a useful mental model for reasoning about how a given result was arrived at.
Its is caluclated like this :-
-10 / 10 = -1 ,
hence remainder 9.
-10 is greatest multiple of 10 which is less than -1.
It is similar to 9 % 5 , will be greatest number less than dividend should be considers.
5/5 = 1 , hence 4.
I'm not sure if you're asking the algorithm that python uses, or why the answer comes out this way.
If the latter, imagine that for modulo n you subtract or add n until you get a number between 0 and n-1 inclusive
For at least python-2.7.9 it is done by first doing the integer division x/y with truncation towards zero. Then the difference of x and the quotient multiplied by y (ie x - (x/y)*y) is calculated. If the result is nonzero and y is of different sign then y is added to the result.
For example with your example x=-1 and y=10, we first calculate x/y which is 0 (-0.1 rounds to 0). The difference then is -1 - 0 which is -1. Now -1 is non-zero and with different sign than 10, so we add 10 to it and get 9.
For python3 (3.4.2) it's a bit more complicated as by python3 the integers are actually longs so the division algorithm is implemented in software rather than hardware, but otherwise basically the same. The division is done as unsigned division using the normal division algorithm using base 2^N for some suitable number N depending on platform.
Related
How do I use math.ceil() to round up a number to the maximum of it's base. For example, if the number is between
0 - 9 -> 9
10 - 99 -> 99
100 - 999 -> 999
1000 - 9999 -> 9999
so forth. I've done it by counting the number of digits but I'm looking for a pythonic way
Here is one way to do this using the ceiling along with logarithms:
def round_by_tens(inp):
z = math.ceil(math.log10(inp+1))
q = (10 ** z) - 1
return q
nums = [5, 50, 500, 5000]
for num in nums:
print(round_by_tens(num))
This prints:
9.0
99.0
999.0
9999.0
The logic here is to first compute the ceiling power of 10 which would be required to generate the tens factor which is the upper bound of the input. Then, we simply take that tens upper bound, and subtract one from it to generate the output you expect.
You can use the following also:
def repeat_to_length(string_to_expand, length):
return int(string_to_expand * length)
num = 0
print(repeat_to_length("9", len(str(num))))
# 9
num = 45
print(repeat_to_length("9", len(str(num))))
# 99
num = 123
print(repeat_to_length("9", len(str(num))))
# 999
I would probably use this:
def round9(x):
r = 10
while x >= 10:
r *= 10
x //= 10
return r-1
I have an excessively big number (1500+) digits and I need to find 2 ** that number modulo 1_000_000_000 so I wrote this python:
n = 1
return_value = 2
while n < To_the_power_of:
return_value *= 2
return_value = return_value % 1_000_000_000
n += 1
This returns the correct value for smaller values, but takes too long for bigger values.
If the number is modulo 10 then you get this pattern which could be used.
2 ** 1 modulo 10 = 2
2 ** 2 modulo 10 = 4
2 ** 3 modulo 10 = 8
2 ** 4 modulo 10 = 6
2 ** 5 modulo 10 = 2
2 ** 6 modulo 10 = 4
2 ** 7 modulo 10 = 8
2 ** 8 modulo 10 = 6
I'm hoping that a similar pattern could be used to answer the original problem.
You already know that the sequence will repeat. You found the cycle of 4 for mod 10; now, just find it for a billion:
mod_billion = set()
pow_2 = 2
billion = 10**9
while pow_2 not in mod_billion:
mod_billion.add(pow_2)
pow_2 *= 2
if pow_2 > billion:
pow_2 -= billion
print (pow_2, len(mod_billion))
Three seconds later, we get:
512 1562508
Thus, this sequence repeats every 1562508 items. To find your value for your given power:
cycle = 1562508
small_power = big_power % cycle
result = (2 ** small_power) % billion
Your code makes about 10 ** 1500 iterations, which is indeed insanely long. A useful general technique is exponentiation by squaring, which will give you the result in about 4500 iterations.
If you want to follow the path of the #Prune's answer, you should go along the lines of Fermat's Little Theorem, specifically the Euler's generalization. phi(1_000_000_000) is easy to compute, because 10 ** 9 = (2 ** 9) * (5 ** 9), the product of 2 powers of primes.
Write a program to compute the sum of the terms of the series: 4 - 8 + 12 - 16 + 20 -
24 + 28 - 32 + .... +/- n, where n is an input. Consider that n is always valid (which
means it follows the series pattern).
n = int(input("Enter n: "))
sum = 0
for i in range(4,n+4,4):
sum += i - (i+2)
print("The sum of %s first terms is: %s"%(n,sum))
Can't seem to find the issues that Ihave
How about an explicit formula?
def sumSeries(n):
if n / 4 % 2 == 0:
return - n / 2
else:
return (n + 4) / 2
The series doesn't do anything too interesting, it just keeps adding +4 every two steps, and flips the sign in even steps:
4 = 4
4 - 8 = -4
4 - 8 + 12 = 8
4 - 8 + 12 - 16 = -8
...
Some examples:
for n in range(4, 100, 4):
print("%d -> %d" % (n, sumSeries(n)))
Output:
4 -> 4
8 -> -4
12 -> 8
16 -> -8
20 -> 12
24 -> -12
28 -> 16
32 -> -16
36 -> 20
40 -> -20
44 -> 24
48 -> -24
52 -> 28
56 -> -28
60 -> 32
64 -> -32
First of all, know that your series sum has a closed form.
def series_sum(n):
sign = 1 if n % 2 else -1
value = (n - 1) // 2 * 4 + 4
return sign * value
series_sum(1) # 4
series_sum(2) # -4
series_sum(3) # 8
But in general, infinite series are a good usecase for generators.
def series():
value = 0
sign = -1
while True:
value += 4
sign *= -1
yield sign * value
s = series()
next(s) # 4
next(s) # -8
next(s) # 12
Thus for getting the sum you can do this.
s = series()
def sum_series(n, s):
return sum(next(s) for _ in range(n))
sum_series(5, s) # 12
An interesting question asked in the comment is also, given some value, how can we recover the sum up until that value is reached in the series. The generator approach is well suited for these kind of problems.
from itertools import takewhile
def sum_until(val):
return sum(x for x in takewhile(lambda x: -val <= x <= val, series()))
sum_until(12) # 8
Python can be used to easily compute mathematical sequences and series.
We find the sum of all values computed up to and including n
Given
the following mathematical components:
generating function (A)
sample alternating arithmetic sequence (B)
summation equation (C)
We now implement two approaches A and C verified by B.
Code
import itertools as it
n = 8
Generating Function, A
seq = [(-1)**(i + 1)*(4 * i) for i in range(1, n + 1)]
sum(seq)
# -16
Summation Equation, C
def f(n):
if n == 1:
return 1
elif n % 2 == 0:
return -n // 2
else:
return (n + 1) // 2
4*f(n)
# -16
Details
Generating Function
This first approach simply sums an arithmetic sequence generated by a list comprehension. The signs of values alternate by the expression (-1)**(i + 1):
seq
# [4, -8, 12, -16, 20, -24, 28, -32]
Similarly, an infinite sequence can be made using a generator expression and itertools.count:
inf_seq = ((-1)**(i + 1)*(4 * i) for i in it.count(1))
sum(it.islice(inf_seq, n))
# -16
Here the sum is returned for a slice of n values. Note, we can use the take itertools recipe and itertools.accumulate to compute some arbitrary number of summations, e.g. 10 sums (see also itertools.takewhile).
def take(n, iterable):
"Return first n items of the iterable as a list"
return list(it.islice(iterable, n))
inf_seq = ((-1)**(i + 1)*(4 * i) for i in it.count(1))
list(take(10, it.accumulate(inf_seq)))
# [4, -4, 8, -8, 12, -12, 16, -16, 20, -20]
Summation Equation
The second approach comes from inspection, where a pattern is determined from the outputs of a sample sequence:
n 4n f(n) 4f(n)
--- ---- ---- -----
1 4 1 -> 4
2 -8 -1 -> -4
3 12 2 -> 8
4 -16 -2 -> -8
5 20 3 -> 12
6 -24 -3 -> -12
7 28 4 -> 16
8 -32 -4 -> -16
9 36 5 -> 20
10 -40 -5 -> -20
For an arbitrary final value n, a value of the sequence is generated (4n). When multiplied with some unknown function, f(n), a resultant sum is computed (4f(n)). We determine a pattern for f(n) by deducing the relationship between the sequence values and expected sums. Once determined, we directly implement a function that computes our desired sums.
Highlights
Mathematical sequences can be generated from list comprehensions.
Infinite sequences can be made from generator expressions.
Mathematical series/generating functions can be computed using reducing functions, e.g. sum(), operator.mul(), etc. applied to sequences.
General summation equations can be implemented as simple Python functions.
As #John Coleman pointed out, sum += i - (i+2) produces one result not as you expected.
Below is my solution:
Using if else to determinate the sign, then sum up. at last, put it into another loop to create the series you'd like.
n = 9
print('N='+str(n), [sum([index*4 if index%2 else index*-4 for index in range(1, num+1)]) for num in range(1, n+1)])
n = 8
print('N='+str(n), [sum([index*4 if index%2 else index*-4 for index in range(1, num+1)]) for num in range(1, n+1)])
Output:
N=9 [4, -4, 8, -8, 12, -12, 16, -16, 20]
N=8 [4, -4, 8, -8, 12, -12, 16, -16]
[Finished in 0.178s]
I have some equation for a type of step function which I obtained with wolfram alpha:
a_n = 1/8 (2 n+(-1)^n-(1+i) (-i)^n-(1-i) i^n+9)
Using in wolfram with any positive integer will yield me a positive integer result however when I try the following in python
import numpy as np
n = 5
i = complex(0,1)
a = (1/8)*((2*n)+(np.power(-1,n))-(1+i)*(np.power(-i,n))-(1-i)*(np.power(i,n))+9)
I'm always stuck with some real + imaginary part. I need to be able to obtain an integer output for a for use in other equations.
Maybe you want int(a.real) at the end.
Also be aware that by default 1/8 will be evaluated as 0 in Python 2.x
(1+i) (-i)^n+(1-i) i^n
is two times the real part of (1-i) i^n which is, for instance
2*cos(pi/2*n)-2*cos(pi/2*(n+1))
or as values
n 0 1 2 3 4 5 6 7 8
expression 2 2 -2 -2 2 2 -2 -2 2
this is subtracted from the alternating sequence to give
n 0 1 2 3 4 5 6 7 8
(-1)^n-expr -1 -3 3 1 -1 -3 3 1 -1
periodically with period 4
This can be computed avoiding all powers and saveguarding for negative n as
3-2*(((n+2) mod 4 +4) mod 4)
adding 2n+9 to complete the expression gives
12+2*n-2*(((n+2) mod 4 +4) mod 4)
which is indeed divisible by 8, so
a = 1+(n+2-(((n+2) % 4 +4) % 4) )/4
now if one considers that this just reduces (n+2) to the next lower multiple of 4, this is equivalent to the simplified
a = 1 + (n+2)/4
using integer division.
when asked the question to count the number of 1s in the binary representation , the first answer came to my mind is to shift the number right and count the least important bit
but there is a saying that when the number is negative , this method will cause infinite loop ?
I tried quickly with python
>>> a = -16
>>> a >> 1
-8
>>> a >> 1
-8
>>> -8 >> 1
-4
>>>
this is what I expect, so what is the issue, will shift the negative number cause the sign bit to be carried over to the right ?
It's true, you will get an infinite loop, because once you get to -1 you can't get out of there:
>>> a = -1
>>> a >> 1
-1
This sounds like homework so I won't give you a full answer, but have a look at the built-in mod function.
See http://docs.python.org/2/reference/expressions.html#shifting-operations: shifting to the right is equivalent with dividing. Then check http://docs.python.org/2/reference/expressions.html#binary-arithmetic-operations: integer divisions implicitely apply floor on the result, so -1 / 2 = -1 since floor(-0.5) = -1, and regardless of the number you start with, you'll finally reach -1. Therefore, you'll end up with an infinite loop.
If we're talking about python's unlimited-precision integers, then any negative number has an infinite number of 1's! So regardless of sign-filling (which you'll also get in C), counting the bits in a negative number is non-sensical except for a fixed bit length.
For a 32-bit or 64-bit int, just shift this many times and stop.
Here are the bits in the 32-bit integer -4.
>>> n = -4
>>> for bit in reversed([ (n>>shift)&1 for shift in range(32) ]):
... print bit,
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0
So to sum them up, it's just
sum( (n>>shift)&1 for shift in range(32) )