I am getting an error when running the following code:
def f(x):
return x**3-x-2
def bisection(f,a,b,app=0.3):
Fa,Fb=f(a),f(b)
if Fa*Fb>0:
raise Exception('Fails')
for i in range(a,b):
x=(a+b)/2
if f*Fa>0:
a=x
else:
b=x
return x
print(bisection(f,{'a':1,'b':2},0.00003))
Below the output I get when running the script above:
TypeError: unsupported operand type(s) for ** or pow(): 'dict' and 'int'
Any ideas on how to solve this?
There are a couple of issues here. In the bisection function you are supposed to give 4 arguments, f which is a function, a and b which are numbers, and a fourth argument app which is not used in your function currently.
The first issue is that you are giving a dictionary instead of the a and b arguments. The following will work better.
bisection(f=f,a=1,b=2,app=0.00003)
I do not know the bisection method, but from what I can tell from a quick scan on the bisection method from Wikipedia, it should be an N_MAX variable which tells how many iterations you will allow before breaking.
Therefore you should not use a for loop and use a while loop instead.
The new algorithm is then
def f(x):
return x**3-x-2
def bisection(f,a,b,app=0.3, N_MAX=10):
Fa,Fb=f(a),f(b)
if Fa*Fb>0:
raise Exception('Fails')
n = 0
while n < N_MAX:
x=(a+b)/2
if f(x)==0 or ((a-b)/2) < app:
return x
n += 1
if f(x) > 0:
a = x
else:
b = x
return x
print(bisection(f,1,2,0.00003, 10))
>>> 1.5
Related
Say I have these two functions:
def s(x,y,z):
if x <= 0:
return y
return z
def f(a,b):
return s(b, a+1, f(a,b-1)+1)
If I were to try and find f(5,2) in my head, it would go like this:
f(5,2) = s(2,6,f(5,1)+1)
f(5,1) = s(1,6,f(5,0)+1)
f(5,0) = s(0,6,f(5,-1)+1) = 6
f(5,1) = 7
f(5,2) = 8
I never evaluate f(5,-1) because it is not needed. The s function is going to return 6, since argument x is zero, thus evaluation of argument z is unnecessary.
If I were however to try and run this in python, it would keep recursing forever or or until I get a maximum recursion depth error, presumably because python wants to evaluate all the arguments before executing the s function.
My question is, how would I go about implementing these functions, or any similar scenario, in such a way that the recursion stops when it is no longer needed? Would it be possible to delay the evaluation of each argument until it is used in the function?
Your mind is working with 'insider knowledge' of how s() works. Python can't, so it can only follow the strict rules that all argument expressions to a call will have to be evaluated before the call can be made.
Python is a highly dynamic language, and at every step of execution, both s and f can be rebound to point to a different object. This means Python can't optimise recursion or inline function logic. It can't hoist the if x <= 0 test out of s() to avoid evaluating the value for z first.
If you as a programmer know the third expression needs to be avoided in certain circumstances, you need to make this optimisation yourself. Either merge the logic in s into f manually:
def f(a, b):
if b <= 0:
return a + 1
return f(a, b - 1) + 1
or postpone evaluating of the third expression until s() has determined if it needs to be calculated at all, by passing in a callable and make s responsible for evaluating it:
def s(x, y, z):
if x <= 0:
return y
return z() # evaluate the value for z late
def f(a, b):
# make the third argument a function so it is not evaluated until called
return s(b, a+1, lambda: f(a, b - 1) + 1)
When a function is called, all arguments are fully evaluated before they're passed to the function. In other words, f(5,-1) is being executed before s is even started.
Fortunately there's an easy way to evaluate expressions on demand: functions. Instead of passing the result of f(a,b-1) to z, pass it a function that computes that result:
def s(x,y,z):
if x <= 0:
return y
return z() # z is a function now
def f(a,b):
return s(b, a+1, lambda:f(a,b-1)+1)
print(f(5,2)) # output: 8
I'm python user and I'm evaluate combination in python.
For two integers m,n, nCm=n!/(m!*(n-m)!)
So, I defined factorial and combination function.
factorial function is working, but combination function does not working.
What is the error?
1> Factorial Function
def factorial(a):
f=1
for i in range(1,a+1):
f=f*i
print(f)
2> Combination Function
def Combination(n,m):
fn=factorial(n)
fm=factorial(m)
fnm=factorial(n-m)
ncm=factorial(n)/(factorial(m)*factorial(n-m))
print(ncm)
In factorial function, For example, factorial(4)=24 is working in python.
But, In combination function,
When I typing Combination(4,2),
24
2
2
24
2
2
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-18-daae2b10838c> in <module>()
----> 1 Combination(4,2)
<ipython-input-17-76c6e425ad35> in Combination(n, m)
3 fm=factorial(m)
4 fnm=factorial(n-m)
----> 5 ncm=factorial(n)/(factorial(m)*factorial(n-m))
6 print(ncm)
7
TypeError: unsupported operand type(s) for *: 'NoneType' and 'NoneType'
What's the matter in my coding?
Instead of printing the output of a function, you should return the result.
def factorial(a):
f=1
for i in range(1,a+1):
f=f*i
return f
def combination(n,m):
return = factorial(n)/(factorial(m)*factorial(n-m))
print combination(4,2)
One more remark: after calculating factorial(n), it will be stored in your fn variable. You shouldn't calculate it again, but rather take that value and "recycle" it.
def factorial(a):
f=1
for i in range(1,a+1):
f=f*i
return f
def Combination(n,m):
fn=factorial(n)
fm=factorial(m)
fnm=factorial(n-m)
ncm=fn/(fm*fnm)
print(ncm)
Combination(4,2)
In your code there is missing return statement in factorial function.
i am trying to find the square root a number through the function sqrt(a). fixedPoint(f, epsilon) is a helper function. the problem is that i get a this TypeError: 'float' object is not callable. i am new to programming, so if anybody can help and find were is the bug and explain what does this error mean ??
def fixedPoint(f, epsilon):
"""
f: a function of one argument that returns a float
epsilon: a small float
returns the best guess when that guess is less than epsilon
away from f(guess) or after 100 trials, whichever comes first.
"""
guess = 1.0
for i in range(100):
if abs(f(guess) - guess) < epsilon:
return guess
else:
guess = f(guess)
return guess
def sqrt(a):
def tryit(x):
return 0.5 * (a/x + x)
return fixedPoint(tryit(a), 0.0001)
In sqrt function, the code is passing the return value of the tryit (which is a float value), not tryit itself.
Passing the function itself will solve the problem.
def sqrt(a):
def tryit(x):
return 0.5 * (a/x + x)
return fixedPoint(tryit, 0.0001)
I'm a beginner to CS, and I've been trying to work through a Python book (Think Python) on my own.
I'm currently on recursion, but I'm a bit stuck.
The exercise asks for me to write a function called do_n that takes a function object and a number, n, as arguments, and that calls the given function n times.
This is my code:
def countdown(n):
if n<= 0:
print 'Blastoff'
return
else:
print n
countdown(n-1)
def do_n(f(n), x):
if x<=0:
return
else:
f(n)
do_n(f, x-1)
do_n(countdown(3), 3)
When I do this, there's an error because of invalid syntax in def do_n(f(n), x). If I change it to:
def do_n(f, x):
if x<=0:
return
else:
f(n)
do_n(f, x-1)
There is an error because n is not defined in the else statement.
How can I make this work?
You are almost there with your second example. It takes a function f and a max count x. n doesn't exist because you haven't written the loop to generate values for n yet. Turns out python has a builtin for that
def do_n(f, x):
for n in range(x):
f(n)
Now do_n takes a function object f and a count x, then calls the function count times. Notice the difference between f (the function object) and f(n) (the result of calling f with the value n). When you want to call do_n, you do it like this:
do_n(countdown, 3)
Not like
do_n(countdown(3), 3) # badness
That last one calls countdown and then calls do_n with its result.
def print_n(s,n):
if n<=0:
return
else:
print(s)
print_n(s,n-1)
def do_n(f,s,n,x):
if x<=0:
return
else:
f(s,n)
do_n(f,s,n,x-1)
do_n(print_n,'Hello',2,2)
It's a tricky one.
Basically, the solution is:
def do_n(f, n):
if n <= 0:
return
f(n)
do_n(f, n-1)
However, if you actually try combining it with print_n then all hell breaks loose.
First of all, we have to add one more argument, s, to the above code to be able to pass any string that we want to print out n times.
Second of all, the above do_n should be able to repeat any passed function n times so long as the function doesn't mess with do_n. Unfortunately, this is exactly what happens here.
The assignment from the book seems clear: "...write a function called do_n that takes a function object and a number, n, as arguments, and that calls the given function n times..." or in other words do_n calls any function passed to it n times. You'd think if we pass s = 'Hello' and n = 3 then do_n(f, s, n) should output 'Hello' 9 times... because print_n('Hello', 3) prints 'Hello' 3 times and do_n(print_n, 'Hello', 3) is supposed to triple that result... gotcha.
What actually happens is in the first instance of recursion do_n does indeed print out 'Hello' 3 times, because print_n says so. But in the next instance do_n prints out 'Hello' only two times, because it has subtracted 3-1 in the previous instance and now print_n('Hello', 2). In the last instance do_n prints 'Hello' only once, for the same reason. So the total amount of 'Hello' output is 6.
Finally, if you use FOR LOOP instead of recursion to define do_n, you will actually get the correct result of 9 outputs:
def print_n(s, n):
if n <= 0:
return
print(s)
print_n(s, n-1)
def do_n(f, s, n):
for i in range(n):
f(s, n)
do_n(print_n, 'Hello', 3)
P.S.
On Page 52 of Think Python 2E we are encouraged to use recursion over for loop:
"For simple examples like this, it is probably easier to use a for loop. But we will see examples later that are hard to write with a for loop and easy to write with recursion, so it is good to start early."
However, in this particular exercise, using recursion forces an output which clashes with the assignment, seeing that do_n and print_n are at odds with each other because constructing do_n with the help of recursion wrongly reduces n in each instance.
Did I get it right?
thinkpython2e
recursion
I know its dumb question but i am trying to grasp the concepts of OOP in Python. Suppose i want to write the program for factorial in Procedural form, i would do something like this
def factorial(n):
num = 1
while n >= 1:
num = num * n
n = n - 1
return num
f = factorial(3)
print f # 6
Now i want to rewrite the same factorial program in OO way. i am not getting how to write this same function using objects and classes.
class Factorial():
def fact(n):
num = 1
while n >= 1:
num = num * n
n = n - 1
return num
f = Factorial()
a = f.fact(3)
print a # TypeError: fact() takes exactly 1 argument (2 given)
I know this can be done more precisely in Functional way by using lambdas and other things, but i am learning the concepts of OOP. What i am doing wrong ?
When you are calling an instance method, by default the current object is passed as the first parameter to the function. In your case,
def fact(n):
when you call it like this
a = f.fact(3)
it will be actually treated like this
a = fact(f, 3)
The reason why the current object is passed is, to let the instance method make changes to the object. (Remember Python doesn't have any other keyword like this, like in some other languages).
But your function's signature doesn't match this (it expects only one parameter). That's why it is throwing
# TypeError: fact() takes exactly 1 argument (2 given)
To fix this, you have to change the signature to something like this
def fact(self, n):
Now, the self parameter will receive the current object being passed.
You forgot the self parameter:
class Factorial():
def fact(self,n): #Forgot the self parameter huh?
num = 1
while n >= 1:
num = num * n
n = n - 1
return num
I recommend you read these too:
explaining the self variable to a beginner
Python 'self' explained
Dive into Python - defining Classes
I would also recommend these article for reading:
An Introduction to Object-Oriented Concepts in Python, Part 1
Unfortunately I cannot put more that 2 links But I'm sure you'll find other 4 parts of these.