Sum of given series - python

I am trying to find the sum for series : 1 − 1 / 2 + 1 / 3 − 1 / 4 + · · · + 1 / 99 − 1 / 100 ** 2 with python.
My code is -
psum = 0
nsum = 0
for k in range(1,100):
if k%2 == 0:
nsum += 1.0/k
else:
psum += 1.0/k
print psum - nsum - 1.0/100**2
The output is 0.69807217931
I don't have the answer and just want to verify if I am doing it right.
This is not a homework question but just random Python practice.

That works fine, but why not just use one "summing" variable (call it total, as a matter of good practice, since there is a built-in called sum which you don't really want to hide), and actually add or subtract from it at each step?
Alternately (pun intended!), actually use that sum function. The range function can be used to skip every other number, too.
>>> sum(1.0/k for k in range(1, 100, 2)) - sum(1.0/k for k in range(2, 100, 2)) - (1.0/100**2)
0.6980721793101952
Or, as steveha shows, you can use logic to sort out whether to add or subtract the number based on whether it's divisible by 2, and handle it with a "weighted" sum (adding 1.0/k or -1.0/k as appropriate). This is why you should learn more math as a programmer :)

Well, I believe
import math
print math.log(2)
would do the trick.

sum(1.0/k if k % 2 else -1.0/k for k in xrange(1, 100)) - 1.0/100**2
The above code does the same thing as your code, and gets the same answer.
Why does the series use 1/k from 1 through 99, and then use 1/k**2 just for k == 100?

The easiest way to see if you're doing it right is to try it with a much shorter series, one that you can check by hand. For example, use range(1, 5) and see if it gives the answer you expect.
For style tips, you can use xrange instead of range. xrange is nice because it just returns each number as it's needed, while range creates a big list of all the numbers. If you did this for range(1, 1000000), it would use up a lot of memory, while xrange wouldn't.
You could also get away with just one variable for the sum instead of two, I think.

Here's my suggestion.
little but more LOC then #steveha but more generic.
getx=lambda x:(1.0/x)*((-1)**((x%2)+1))
num=100
sum((getx(x) for x in xrange(1,num)))+getx(num)**2
0.688172179310195

Related

Should I consider whether an input value is even or odd when calculating time complexity?

I have the following function:
def pascal_triangle(i:int,j:int):
j = min(j, i-j + 1)
if i == 1 or j == 1:
return 1
elif j > i or j == 0 or i < 1 or j < 1:
return 0
else:
return pascal_triangle(i-1,j-1) + pascal_triangle(i-1,j)
The input value for j has the following constraint:
1<=j<=i/2
My computation for the time complexity is as follows:
f(i,j) = f(i-1,j-1) + f(i-1,j) = f(i-n,j-n) + ... + f(i-n,j)
So, to find the max n, we have:
i-n>=1
j-n>=1
i-n>=j
and, since we know that:
j>=1
j<=i/2
The max n is i/2-1, so the time complexity is O(2^(i/2-1)), and the space complexity is the maximum depth of recursion(n) times needed space for each time(O(1)), O(2^*(i/2-1)).
I hope my calculation is correct. Now my concern is that if i is odd, This number is not divisible by 2, but the terms of function must be an integer. Therefore, I want to know should I write the time complexity like this:
The time complexity and space complexity of the function are both:
O(2^(i/2-1)) if i is even
O(2^(i/2-0.5)) if i is odd
At a first glance, the time and space analysis looks (roughly) correct. I haven't made a super close inspection, however, since it doesn't appear to be the focus of the question.
Regarding the time complexity for even / odd inputs, the answer is that the time complexity is O(sqrt(2)^i), regardless of whether i is even or odd.
In the even case, we have O(2^(i / 2 - 1)) ==> O(1/2 * sqrt(2)^i) ==> O(sqrt(2)^i).
In the odd case, we have O(2^(i / 2 - 0.5)) ==> O(sqrt(2) / 2 * sqrt(2)^i) ==> O(sqrt(2)^i).
What you've written is technically correct, but significantly more verbose than necessary. (At the very least, it's poor style, and if this question was on a homework assignment or an exam, I personally think one could justify a penalty on this basis.)

Sum of 1st N natural numbers in O(no. of digits in N)

I'm trying to write a program to find sum of first N natural numbers i.e. 1 + 2 + 3 + .. + N modulo 1000000009
I know this can be done by using the formula N * (N+1) / 2 but I'm trying to find a sort of recursive function to calculate the sum.
I tried searching the web, but I didn't get any solution to this.
Actually, the problem here is that the number N can have upto 100000 digits.
So, here is what I've tried until now.
First I tried splitting the number into parts each of length 9, then convert them into integers so that I can perform arithmetic operations using the operators for integers.
For example, the number 52562372318723712 will be split into 52562372 & 318723712.
But I didn't find a way to manipulate these numbers.
Then again I tried to write a function as follows:
def find_sum(n):
# n is a string
if len(n) == 1:
# use the formula if single digit
return int(int(n[0]) * (int(n[0]) + 1) / 2)
# I'm not sure what to return here
# I'm expecting some manipulation with n[0]
# and a recursive call to the function itself
# I've also not used modulo here just for testing with smaller numbers
# I'll add it once I find a solution to this
return int(n[0]) * something + find_sum(n[1:])
I'm not able to find the something here.
Can this be solved like this?
or is there any other method to do so?
NOTE: I prefer a solution similar to the above function because I want to modify this function to meet my other requirements which I want to try myself before asking here. But if it is not possible, any other solution will also be helpful.
Please give me any hint to solve it.
Your best bet is to just use the N*(N+1)/2 formula -- but using it mod p. The only tricky part is to interpret division by 2 -- this had to be the inverse of 2 mod p. For p prime (or simply for p odd) this is very easy to compute: it is just (p+1)//2.
Thus:
def find_sum(n,p):
two_inv = (p+1)//2 #inverse of 2, mod p
return ((n%p)*((n+1)%p)*two_inv)%p
For example:
>>> find_sum(10000000,1000000009)
4550000
>>> sum(range(1,10000001))%1000000009
4550000
Note that the above function will fail if you pass an even number for p.
On Edit as #user11908059 observed, it is possible to dispense with multiplication by the modular inverse of 2. As an added benefit, this approach no longer depends on the modulus being odd:
def find_sum2(n,k):
if n % 2 == 0:
a,b = (n//2) % k, (n+1) % k
else:
a,b = n % k, ((n+1)//2) % k
return (a*b) % k

Improving perfomance(speed) of exponent problem

I'm currently learning Python on repl.it and I have a problem with one of my work.
My code is supposed to:
1.Input a given integer X
2.Find the greatest integer n where 2ⁿ is less than or equal to X.
3.Print the exponent value(n) and the result of the expression 2ⁿ.
But my code fail as the machine insert too big number like 10^8+2. The program completely failed
Here is the piece of code that I'm working on:
X = int(input())
a = X//2
while a > -1:
if (2**a) < =x:
print(a)
print(2**a)
break
else:
a -= 1
Can anyone find me another solution to this problem, or improve the bit of code I'm working on by its runtime? It works with small number(less than 10^6) but otherwise the program freeze.
Thanks in advance!
Of course, I can't refer to the "too big input" that you mention (since you didn't provide it), but as for the problem itself, it could be easier solved in the following way:
import numpy as np
a = int(np.log2(your_input))
The first issue I see is that in you code
if (2**a) < =x:
print(a)
print(2**a)
you calculate the value of 2**a twice. A good start could be to save the value of 2**a into a variable. However, since you are only doing powers of 2 you could also take a look at bitwise operations. So instead of doing a = X//2 you could also write
a= X >> 2
and instead of doing 2**a write
temp = 1 << a
When working with powers of 2 it can be significantly faster to work with bitwise operations.
I did it! (using some of your solutions of course)
This is my teachers code :
x = int(input())
n = 1
while 2 ** n <= x:
n += 1
print(n - 1, 2 ** (n - 1))

Calculating the sum of a series?

This is my assignment and for the life of me i cant seem to think of a way to do it. This is the code I have so far:
sum = 0
k = 1
while k <= 0.0001:
if k % 2 == 1:
sum = sum + 1.0/k
else:
sum = sum - 1.0/k
k = k + 1
print()
This is my assignment :
Create a python program named sumseries.py that does the following:
Put comments at the top of your program with your name, date, and
description of what the program does.
Write a program to calculate and display the sum of the series:
1 - 1/2 + 1/3 - 1/4 + ...
until a term is reached that is less than 0.0001.
The answer with 10,000 iterations appears to be 0.6930971830599583
I ran the program with 1,000,000,000 (billion) iterations and came up with a number of 0.6931471810606472. I need to create a loop to programmably create the series.
Actually, you could write this shorter:
Answer = sum(1.0 / k if k % 2 else -1.0 / k for k in range(1, 10001))
What this code does:
the innermost part is a generator expression, which computes the elements of a series 'on the fly'
1.0 / k if k % 2 else -1.0 / k results in 1.0 / k if k is odd and -1.0 / k otherwise (a - b is the same as a + (-b))
for k in range(1, 10001) goes through all ks in range from 1 (included) to 10001 (excluded)
sum can compute the sum of any sequence (any iterable, to be precise), be it a list, a tuple, or a generator expression
The same without generator expressions:
Answer = 0
for k in range(1, 10001):
if k % 2:
Answer += 1.0 / k
else:
Answer -= 1.0 / k
# or simply:
# Answer += 1.0 / k if k % 2 else -1.0 / k
You're almost there, all you need to do is to replace
while k <= 0.0001:
with:
while term <= 0.0001:
term is naturally 1/k
To make the teacher happy, you must follow the details of the problem, as well as the spirit of the problem. The problem clearly states to print the sum, not all the partial sums. You will anger the teacher by submitting a solution that spews 10000 lines of crap not requested.
Some have suggested pre-calculating a loop limit of 10000, but that was not the requested algorithm. Instead, one is to calculate successive terms (1, -1/2, 1/3, -1/4, ...) until reaching a term less than 0.0001.
The reason the problem was specified that way is that one ends up with a more generally useful program, applicable to a wide class of term formulas. Not a fragile one that gets the wrong answer if the term formula is changed from (-1)**(k-1)/k, to say 1/k or 1/k^2.
The teacher's wording "term less than 0.0001" is imprecise and assumed some math knowledge. They want the magnitude (absolute value) of the term to be less than 0.0001. Otherwise, iteration would stop at the second term -1/2, as someone pointed out.
So, this answer would not be complete without a pompous pedantic solution that skips ahead a chapter. ;) Note that previous some answers will not work in Python2.x without a conversion to float.
def term(k):
return (-1)**(k - 1) / float(k)
err = 0.0001
def terms():
k = 1
t = term(k)
while abs(t) >= err:
yield t
k += 1
t = term(k)
print(sum(terms()))
Here is the answer your teacher is looking for for full credit.
until < .0001 means while >= 0.0001 This modifies your code the least, so makes it a correction of what you wrote
sum = 0
k = 1
while 1.0/k >= 0.0001:
if k % 2 == 1:
sum = sum + 1.0/k
else:
sum = sum - 1.0/k
k = k + 1
print(sum)
Absolutly simplest way would be the following
sum((-1)**(k) / k for k in range(1, 10001))

Taking square of summed numbers

This code adds all natural numbers up to 10, then takes the square of that sum in Python. Where did I go wrong?
def square_of_sum():
sum = 0
for x in xrange(11):
if x <= 10:
x + sum = sum
x += 1
else:
print sum*sum
break
Ah, I see you like Project Euler :)
Solution
I think this is what you meant by your code:
def square_of_sum():
sum_ = 0
for x in xrange(1, 11):
sum_ += x
return sum_ ** 2
To rewrite this more idiomatically, use generator comprehensions and built-ins:
def square_of_sum():
return sum(range(11)) ** 2
If your performance conscious, you can eliminate the loop by noticing that your finding the sum of an arithmetic series:
def square_of_sum(x):
print (x * (x + 1) / 2) ** 2
Fixes
As to why your code isn't working, it's b'coz of many reasons.
First of all, I think you're confused about how the for loop in Python works. Basically, it just loops over an array. You didn't have to check and break when x became greater than 10, nor increment it. Read up on the Python docs on how to use the for loop. To see an example of when to use it, see the wiki page.
Secondly, variable assignments are done with the variable on the left and the expression to be evaluated on the right. So x + sum = sum should really have been sum = sum + x or sum += x for brevity.
Thirdly, sum is a built-in function. You probably didn't want to nor shouldn't over-shadow it, so rename your sum variable to something else.
And last, sum*sum is equivalent to just raising it to the power of 2 and you can do that using the ** operator as so: sum ** 2.
Hope this helped you understand.
To fix the errors in your code:
def square_of_sum():
s = 0
for x in xrange(11):
s += x
print s**2
or, more idiomatically,
def square_of_sum(n):
print sum(range(n + 1)) ** 2
or, to eliminate the loop:
def square_of_sum(n):
print (n * (n + 1) / 2) ** 2
A couple of problems. First of all, sum is a builtin function, so you probably don't want to name anything that, so use a variable called something like total instead.
Second, variables assignment is done with the variable on the left and the expression on the right, so x + total = total should be total = x + total, or total += x for brevity.
Third, since the case when x == 11 is basically just a return case, it should be outside the loop.
And, finally, total * total is equivalent to total ** 2; this is easier to use for things like
def square_of_sum():
total = 0
for x in xrange(11):
if x <= 10:
total += x
x += 1
print total ** 2
But, if I were you, I'd just use
sum(range(11))**2

Categories

Resources