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
Related
I've been trying to solve this infinite sum with a given precision problem.
You can see the description in the picture below
Here's what I tried so far:
import math
def infin_sum(x, eps):
sum = float(0)
prev = ((-1)*(x**2))/2
i = 2
while True:
current = prev + ((-1)**i) * (x**(2*i)) / math.factorial(2*i)
if(abs(current - prev) <= eps):
print(current)
return current
prev = current
i+=1
For the given sample input (0.2 for x and 0.00001 precision) my sum is 6.65777777777778e-05 and according to their tests it doesn't come close enough to the correct answer
You should use math.isclose() instead of abs() to check your convergence (given that it's how the result will be checked). given that each iteration adds or subtract a specific term, the delta between previous and next (Si-1 vs Si) will be equal to the last term added (so you don't need to track a previous value).
That infinite series is almost the one for cosine (it would be if i started at zero) so you can test your result against math.cos(x)-1. Also, I find it strange that the check for expected result is fixed within a precision 0.0001 but the sample input specifies a precision of 0.00001 (I guess more precise will be within 0.0001 but then, the validation is not really checking that the output is correct given the input?)
from math import isclose
def cosMinus1(x,precision=0.00001):
result = 0
numerator = 1
denominator = 1
even = 0
while not isclose(numerator/denominator,0,abs_tol=precision): # reach precision
numerator *= -x*x # +/- for even powers of x
even += 2
denominator *= even * (even-1) # factorial of even numbers
result += numerator / denominator # sum of terms
return result
print(cosMinus1(0.2))
# -0.019933422222222226
import math
expected = math.cos(0.2)-1
print(expected, math.isclose(expected,cosMinus1(0.2),abs_tol=0.0001))
# -0.019933422158758374 True
Since it's not a good idea to shadow sum, you had the right idea in calling it current, but you didn't initialise current to float(0), and forgot to sum it. This is your code with those problems fixed:
def infin_sum(x, eps):
current = float(0)
prev = ((-1) * (x ** 2)) / 2
i = 2
while True:
current = current + (((-1) ** i) * (x ** (2 * i))) / math.factorial(2 * i)
if (abs(current - prev) <= eps):
print(current)
return current
prev = current
i += 1
As a more general comment, printing inside a function like this is probably not the best idea - it makes the reusability of the function limited - you'd want to capture the return value and print it outside the function, ideally.
First, you are not summing the elements.
Recomputing everything from scratch is very wasteful and precision of floats is limited.
You can user Horner's method to refine the sum:
import math
def infin_sum(x, eps):
total = float(0)
e = 1
total = 0
i = 1
while abs(e) >= eps:
diff = (-1) * (x ** 2) / (2 * i) / (2 * i - 1)
e *= diff
total += e
i += 1
return total
if __name__ == "__main__":
x = infin_sum(0.2, 0.00001)
print(x)
Dont forget to add the result and not replace it:
prev += current
instead of
prev = current
So, I was asked to code the Wallis product and it wasn't supposed to be really complicated. So I made a code but apparently, it could only work for Wallis(1) and not the rest. Could anyone help me? Thank you!
def Wallis (n):
result = 1
for count in range(2, n+2, 2):
result = result * (count**2/((count-1)*(count+1)))
return result
Formula to compute Wallis product
(2*2)/(3*5) * (4*4)/(5*7) * (6*6)/(7*9) and so on until ((n*2) ** 2)/ ((n-1)* (n+1))
Output
Wallis(1) = (2*2)/(3*5) = 0.267
Wallis(2) = Wallis(1) * (4*4)/(5*7) = 0.122
As others said, your range() needs to be changed.
For n=3,
for count in range(2, n+2, 2):
print(i)
would print
2
4
but you needed 6 as well.
As Python documentation says
class range(start, stop[, step])
For a positive step, the contents of a range r are determined by the formula r[i] = start + step*i where i >= 0 and r[i] < stop.
meaning stop is not included.
Here step is 2, you could use
for count in range(2, 2*(n+1), 2):
And exponentiation is costlier than multiplication. So
count*count
is better than
count**2
So the modified version could be
def Wallis(n):
result=1
for count in range(2, 2*(n+1), 2):
result*=((count*count)/((count-1)*(count+1)))
return result
Note that the value returned by Wallis is only half the value of Pi.
You could modify the return statement to
return result*2
if you want.
Mainly your range command is wrong:
range(2, 2*n+2, 2)
Alternatively, you can move the complexity to the formula, i.e.:
for count in range(1, n):
result = result * (4*count*count/((2*count-1)*(2*count+1)))
The problem with your code is that count is equal to 2*n in your equation so in (count**2/((count-1)*(count+1))), count**2 is the same as (2*n)**2 however the following count-1 should be the same as n-1 but rather it is actually (2*n)-1. The same goes for count+1.
I made my own version which should help you (although I used a different equation which is at https://www.wikiwand.com/en/Wallis_product)
def wallis(limit):
result = 1
for x in range(2, limit, 2):
result *= (x / (x - 1)) * (x / (x + 1))
return result
As limit gets higher, it converges closer to half pi.
This is what I have to program:
sen(x) = (x/1!) - (x^3/3!) + (x^5/5!) - (x^7/7!) + ...
So far I have this:
def seno(x, n):
for i in range(1, n+1, 2):
result = (x**i/math.factorial(i))
result1 = (x**i/math.factorial(i))
result2 = (x**i/math.factorial(i))
result3 = (x**i/math.factorial(i))
return math.sin(result-result1 + result2 - result3)
The thing I can’t understand is how to actually change the i value for each result.
Another thing is I can’t use any non-built-in function. So no imports except for the math.
EDIT: Thank you for the quick reply.
It looks like you're doing a Taylor Series approximation of Sine.
You probably shouldn't declare separate result1, result2, etc. Instead, you compute each value in a loop, and accumulate it in a single result variable.
def seno(x,n):
result = 0
sign = 1 # Sign starts out positive
for i in range(1, n+1, 2):
result += x**i/math.factorial(i)
sign *= -1 # use negative sign on odd terms
return result
Note that you don't actually call math.sin on the result. The whole point of using a Taylor Series approximation is to estimate the value of math.sin(x) without actually calling that function.
You can optimize this loop a bit more. You can do a strength reduction on math.factorial by accumulating the answer rather than recomputing the whole factorial value on each iteration. You can also do a similar strength reduction on the x**i term, and roll the sign-switching logic into the update logic for exp as well.
def seno(x,n):
result = 0.0
fact = 1.0 # start with '1!'
exp = x # start with 'x¹'
xx = x*x # xx = x²
for i in range(1, n+1, 2):
result += exp / fact
exp *= -xx # update exponential term to 'xⁱ', and swap sign
fact *= (i+1) * (i+2) # update factorial term to '(i+2)!'
return result
You are using the for loop incorrectly. Each iteration will compute one term of the series; you need to accumulate those values rather than trying to set 4 results at a time.
def seno(x, n):
sign = 1
result = 0
for i in range(1, n+1, 2):
term = x**i/math.factorial(i)
result += sign * term
sign *= -1 # Alternate the sign of the term
return result
I am trying to write a program using Python v. 2.7.5 that will compute the area under the curve y=sin(x) between x = 0 and x = pi. Perform this calculation varying the n divisions of the range of x between 1 and 10 inclusive and print the approximate value, the true value, and the percent error (in other words, increase the accuracy by increasing the number of trapezoids). Print all the values to three decimal places.
I am not sure what the code should look like. I was told that I should only have about 12 lines of code for these calculations to be done.
I am using Wing IDE.
This is what I have so far
# base_n = (b-a)/n
# h1 = a + ((n-1)/n)(b-a)
# h2 = a + (n/n)(b-a)
# Trap Area = (1/2)*base*(h1+h2)
# a = 0, b = pi
from math import pi, sin
def TrapArea(n):
for i in range(1, n):
deltax = (pi-0)/n
sum += (1.0/2.0)(((pi-0)/n)(sin((i-1)/n(pi-0))) + sin((i/n)(pi-0)))*deltax
return sum
for i in range(1, 11):
print TrapArea(i)
I am not sure if I am on the right track. I am getting an error that says "local variable 'sum' referenced before assignment. Any suggestions on how to improve my code?
Your original problem and problem with Shashank Gupta's answer was /n does integer division. You need to convert n to float first:
from math import pi, sin
def TrapArea(n):
sum = 0
for i in range(1, n):
deltax = (pi-0)/n
sum += (1.0/2.0)*(((pi-0)/float(n))*(sin((i-1)/float(n)*(pi-0))) + sin((i/float(n))*(pi-0)))*deltax
return sum
for i in range(1, 11):
print TrapArea(i)
Output:
0
0.785398163397
1.38175124526
1.47457409274
1.45836902046
1.42009115659
1.38070223089
1.34524797198
1.31450259385
1.28808354
Note that you can heavily simplify the sum += ... part.
First change all (pi-0) to pi:
sum += (1.0/2.0)*((pi/float(n))*(sin((i-1)/float(n)*pi)) + sin((i/float(n))*pi))*deltax
Then do pi/n wherever possible, which avoids needing to call float as pi is already a float:
sum += (1.0/2.0)*(pi/n * (sin((i-1) * pi/n)) + sin(i * pi/n))*deltax
Then change the (1.0/2.0) to 0.5 and remove some brackets:
sum += 0.5 * (pi/n * sin((i-1) * pi/n) + sin(i * pi/n)) * deltax
Much nicer, eh?
You have some indentation issues with your code but that could just be because of copy paste. Anyways adding a line sum = 0 at the beginning of your TrapArea function should solve your current error. But as #Blender pointed out in the comments, you have another issue, which is the lack of a multiplication operator (*) after your floating point division expression (1.0/2.0).
Remember that in Python expressions are not always evaluated as you would expect mathematically. Thus (a op b)(c) will not automatically multiply the result of a op b by c like you would expect with a mathematical expression. Instead this is the function call notation in Python.
Also remember that you must initialize all variables before using their values for assignment. Python has no default value for unnamed variables so when you reference the value of sum with sum += expr which is equivalent to sum = sum + expr you are trying to reference a name (sum) that is not binded to any object at all.
The following revision to your function should do the trick. Notice how I place multiplication operators (*) between every expression that you intend to multiply.
def TrapArea(n):
sum = 0
for i in range(1, n):
i = float(i)
deltax = (pi-0)/n
sum += (1.0/2.0)*(((pi-0)/n)*(sin((i-1)/n*(pi-0))) + sin((i/n)*(pi-0)))*deltax
return sum
EDIT: I also dealt with the float division issue by converting i to float(i) within every iteration of the loop. In Python 2.x, if you divide one integer type object with another integer type object, the expression evaluates to an integer regardless of the actual value.
A "nicer" way to do the trapezoid rule with equally-spaced points...
Let dx = pi/n be the width of the interval. Also, let f(i) be sin(i*dx) to shorten some expressions below. Then interval i (in range(1,n)) contributes:
dA = 0.5*dx*( f(i) + f(i-1) )
...to the sum (which is an area, so I'm using dA for "delta area"). Factoring out the 0.5*dx, makes the whole some look like:
A = 0.5*dx * ( (f(0) + f(1)) + (f(1) + f(2)) + .... + (f(n-1) + f(n)) )
Notice that there are two f(1) terms, two f(2) terms, on up to two f(n-1) terms. Combine those to get:
A = 0.5*dx * ( f(0) + 2*f(1) + 2*f(2) + ... + 2*f(n-1) + f(n) )
The 0.5 and 2 factors cancel except in the first and last terms:
A = 0.5*dx(f(0) + f(n)) + dx*(f(1) + f(2) + ... + f(n-1))
Finally, you can factor dx out entirely to do just one multiplication at the end. Converting back to sin() calls, then:
def TrapArea(n):
dx = pi/n
asum = 0.5*(sin(0) + sin(pi)) # this is 0 for this problem, but not others
for i in range(1, n-1):
asum += sin(i*dx)
return sum*dx
That changed "sum" to "asum", or maybe "area" would be better. That's mostly because sum() is a built-in function, which I'll use below the line.
Extra credit: The loop part of the sum can be done in one step with a generator expression and the sum builtin function:
def TrapArea2(n):
dx = pi/n
asum = 0.5*(sin(0) + sin(pi))
asum += sum(sin(i*dx) for i in range(1,n-1))
return asum*dx
Testing both of those:
>>> for n in [1, 10, 100, 1000, 10000]:
print n, TrapArea(n), TrapArea2(n)
1 1.92367069372e-16 1.92367069372e-16
10 1.88644298557 1.88644298557
100 1.99884870579 1.99884870579
1000 1.99998848548 1.99998848548
10000 1.99999988485 1.99999988485
That first line is a "numerical zero", since math.sin(math.pi) evaluates to about 1.2e-16 instead of exactly zero. Draw the single interval from 0 to pi and the endpoints are indeed both 0 (or nearly so.)
I'm working to finish a math problem that approximates the square root of a number using Newton's guess and check method in Python. The user is supposed to enter a number, an initial guess for the number, and how many times they want to check their answer before returning. To make things easier and get to know Python (I've only just started learning the language a couple of months ago) I broke it up into a number of smaller functions; the problem now, though, is that I'm having trouble calling each function and passing the numbers through.
Here is my code, with comments to help (each function is in order of use):
# This program approximates the square root of a number (entered by the user)
# using Newton's method (guess-and-check). I started with one long function,
# but after research, have attempted to apply smaller functions on top of each
# other.
# * NEED TO: call functions properly; implement a counting loop so the
# goodGuess function can only be accessed the certain # of times the user
# specifies. Even if the - .001 range isn't reached, it should return.
# sqrtNewt is basically the main, which initiates user input.
def sqrtNewt():
# c equals a running count initiated at the beginning of the program, to
# use variable count.
print("This will approximate the square root of a number, using a guess-and-check process.")
x = eval(input("Please type in a positive number to find the square root of: "))
guess = eval(input("Please type in a guess for the square root of the number you entered: "))
count = eval(input("Please enter how many times would you like this program to improve your initial guess: "))
avg = average(guess, x)
g, avg = improveG(guess, x)
final = goodGuess(avg, x)
guess = square_root(guess, x, count)
compare(guess, x)
# Average function is called; is the first step that gives an initial average,
# which implements through smaller layers of simple functions stacked on each
# other.
def average(guess, x) :
return ((guess + x) / 2)
# An improvement function which builds upon the original average function.
def improveG(guess, x) :
return average(guess, x/guess)
# A function which determines if the difference between guess X guess minus the
# original number results in an absolute vale less than 0.001. Not taking
# absolute values (like if guess times guess was greater than x) might result
# in errors
from math import *
def goodGuess(avg, x) :
num = abs(avg * avg - x)
return (num < 0.001)
# A function that, if not satisfied, continues to "tap" other functions for
# better guess outputs. i.e. as long as the guess is not good enough, keep
# improving the guess.
def square_root(guess, x, count) :
while(not goodGuess(avg, x)):
c = 0
c = c + 1
if (c < count):
guess = improveG(guess, x)
elif (c == count):
return guess
else :
pass
# Function is used to check the difference between guess and the sqrt method
# applied to the user input.
import math
def compare(guess, x):
diff = math.sqrt(x) - guess
print("The following is the difference between the approximation")
print("and the Math.sqrt method, not rounded:", diff)
sqrtNewt()
Currently, I get this error: g, avg = improveG(guess, x)
TypeError: 'float' object is not iterable.
The final function uses the final iteration of the guess to subtract from the math square root method, and returns the overall difference.
Am I even doing this right? Working code would be appreciated, with suggestions, if you can provide it. Again, I'm a newbie, so I apologize for misconceptions or blind obvious errors.
Implementation of the newton method:
It should be fairly easy to add little tweaks to it when needed. Try, and tell us when you get stuck.
from math import *
def average(a, b):
return (a + b) / 2.0
def improve(guess, x):
return average(guess, x/guess)
def good_enough(guess, x):
d = abs(guess*guess - x)
return (d < 0.001)
def square_root(guess, x):
while(not good_enough(guess, x)):
guess = improve(guess, x)
return guess
def my_sqrt(x):
r = square_root(1, x)
return r
>>> my_sqrt(16)
4.0000006366929393
NOTE: you will find enough exaples on how to use raw input here at SO or googling, BUT, if you are counting loops, the c=0 has to be outside the loop, or you will be stuck in an infinite loop.
Quiqk and dirty, lots of ways to improve:
from math import *
def average(a, b):
return (a + b) / 2.0
def improve(guess, x):
return average(guess, x/guess)
def square_root(guess, x, c):
guesscount=0
while guesscount < c :
guesscount+=1
guess = improve(guess, x)
return guess
def my_sqrt(x,c):
r = square_root(1, x, c)
return r
number=int(raw_input('Enter a positive number'))
i_guess=int(raw_input('Enter an initial guess'))
times=int(raw_input('How many times would you like this program to improve your initial guess:'))
answer=my_sqrt(number,times)
print 'sqrt is approximately ' + str(answer)
print 'difference between your guess and sqrt is ' + str(abs(i_guess-answer))
The chosen answer is a bit convoluted...no disrespect to the OP.
For anyone who ever Googles this in the future, this is my solution:
def check(x, guess):
return (abs(guess*guess - x) < 0.001)
def newton(x, guess):
while not check(x, guess):
guess = (guess + (x/guess)) / 2.0
return guess
print newton(16, 1)
Here's a rather different function to compute square roots; it assumes n is non-negative:
def mySqrt(n):
if (n == 0):
return 0
if (n < 1):
return mySqrt(n * 4) / 2
if (4 <= n):
return mySqrt(n / 4) * 2
x = (n + 1.0) / 2.0
x = (x + n/x) / 2.0
x = (x + n/x) / 2.0
x = (x + n/x) / 2.0
x = (x + n/x) / 2.0
x = (x + n/x) / 2.0
return x
This algorithm is similar to Newton's, but not identical. It was invented by a Greek mathematician named Heron (his name is sometimes spelled Hero) living in Alexandria, Egypt in the first century (about two thousand years ago). Heron's recurrence formula is simpler than Newton's; Heron used x' = (x + n/x) / 2 where Newton used x' = x - (x^2 - n) / 2x.
The first test is a special case on zero; without it, the (n < 1) test causes an infinite loop. The next two tests normalize n to the range 1 < n <= 4; making the range smaller means that we can easily compute an initial approximation to the square root of n, which is done in the first computation of x, and then "unroll the loop" and iterate the recurrence equation a fixed number of times, thus eliminating the need for testing and recurring if the difference between two successive loops is too large.
By the way, Heron was a pretty interesting fellow. In addition to inventing a method for calculating square roots, he built a working jet engine, a coin-operated vending machine, and lots of other neat stuff!
You can read more about computing square roots at my blog.
it shouldnt have to be that complicated i wrote this up
def squareroot(n,x):
final = (0.5*(x+(n/x)))
print (final)
for i in range(0,10):
final = (0.5*(final+(n/final)))
print (final)
or you could change it to be like this
n = float(input('What number would you like to squareroot?'))
x = float(input('Estimate your answer'))
final = (0.5*(x+(n/x)))
print (final)
for i in range(0,10):
final = (0.5*(final+(n/final)))
print (final)
All you need to know is the nth term in the sequence. From the Leibniz series, we know this is ((-1)**n)/((2*n)+1). Just sum this series for all i with an initial condition of zero and you're set.
def myPi(n):
pi=0
for i in range(0,n):
pi=pi+((-1)**i)/((2*i)+1)
return 4*pi
print (myPi(10000))