Square root function in Python - what's wrong with it? - python

I literally just started learning Python this week. (I will be a computer science fresher in a month!)
Here's a function I wrote to compute the square root of x.
#square root function
def sqrt(x):
"""Returns the square root of x if x is a perfect square.
Prints an error message and returns none if otherwise."""
ans = 0
if x>=0:
while ans*ans <x:
ans = ans + 1
if ans*ans == x:
print(x, 'is a perfect square.')
return ans
else:
print(x, 'is not a perfect square.')
return None
else: print(x, 'is a negative number.')
But when I save it and type sqrt(16) into the Python shell, I get an error message.
NameError: name 'sqrt' is not defined
I'm using Python 3.1.1.
Is there something wrong with my code?
Any help would be appreciated.
Thanks
UPDATE
Okay, thanks to you guys I realized I hadn't imported the function.
And when I tried to import it, I got an error because I saved it in a generic My Documents file instead of C:\Python31. So after saving the script as C:\Python31\squareroot.py, I typed into the shell (having restarted it):
import squareroot
And got a NEW error!
>>> import squareroot
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
import squareroot
File "C:\Python31\squareroot.py", line 13
return ans
SyntaxError: 'return' outside function
Meaning there WAS a bug in my original code! I'm going to look at some of the suggested corrections below right now. If you've spotted anything else, say. Thanks :)
UPDATE 2 - IT WORKED!!!!!!!!!!
Here's what I did.
First, I used a cleaned up version of code kindly posted by IamChuckB. I made a new script with this in it (changed the function name from sqrt to sqrta to differentiate):
def sqrta(x):
"""Returns the square root of x if x is a perfect square.
Prints an error message and returns none if otherwise."""
ans = 0
if x>=0:
while ans*ans <x:
ans = ans + 1
if ans*ans == x:
print(x, 'is a perfect square.')
return ans
else:
print(x, 'is not a perfect square.')
return None
else:
print(x, 'is a negative number.')
And, importantly, saved it as C:\Python31\squareroota.py (Again, added an "a" at the end to differentiate between this the other, failed, file.)
Then I reopened Python shell and did this:
>>> import squareroota
Nothing happened, no error, great! Then I did this:
>>> squareroota.sqrta(16)
And got this!
16 is a perfect square.
4
Wow. I know this might seem like playing with ABC blocks in school but it honestly blew my mind. Thank you very much everyone!

Yes I believe you have to actually import your function into the shell.
from yourfile import sqrt
Be careful. I think if you're in the shell and you make changes, you have to reimport your function for those changes to show up. As delnan mentions below you can reload
your file after changeing it..

Firstly, your loop will always end on its first iteration since you essentially have if (...) return else return. Try this instead:
def sqrt(x):
"""Returns the square root of x if x is a perfect square.
Prints an error message and returns none if otherwise."""
ans = 0
if x >= 0:
while ans * ans <= x:
if ans * ans == x:
print(x, 'is a perfect square.')
return ans
ans = ans + 1
print(x, 'is not a perfect square.')
return None
else: print(x, 'is a negative number.')
But note that Python offers a built-in power operator:
def sqrt(x):
return x ** 0.5
To answer your question specifically, you will have to import your function. If the file in which this is written is sqrt.py, to use this function in another file you would need from sqrt import sqrt.

The NameError means that your python shell does not recognize the function. You probably forgot to import the script.
Assuming that you saved your file as myscript.py (in the same directory as where you start your python shell), you have to use:
import myscript
for the functions defined inside to be available. Note that you'll have to call myscript.sqrt in order to run your function sqrt: it is only available in the myscript namespace.
An alternative is to type from myscript import sqrt: in that case, you make your myscript.sqrt available in the namespace as sqrt. Be careful that you don't overwrite a builtin function with this from ... import ......

Here's your original code, just cleaned up so it will run. The problem with it as originally formatted was with indentation.
The while block should be indented one level (4 spaces) deep to denote it is in the def block for the function sqrt.
Having the if/else blocks inside of the while statements means that check is done each pass through the loop; therefore, the first time through when ans is only equal to one, that test will be done, your output with be printed and a value returned. We need to change this. Several of the other answers give more straight-forward ways to phrase this in python but, in keeping as close to the code you've written as possible, all you actually have to do is move the if block and the else block out of the while block. Code is shown below:
def sqrt(x):
"""Returns the square root of x if x is a perfect square.
Prints an error message and returns none if otherwise."""
ans = 0
if x>=0:
while ans*ans <x:
ans = ans + 1
if ans*ans == x:
print(x, 'is a perfect square.')
return ans
else:
print(x, 'is not a perfect square.')
return None
else:
print(x, 'is a negative number.')
Sample input and output are shown:
In:
sqrt(9)
Out:
9 is a perfect square.
In:
sqrt(8)
Out:
8 is not a perfect square.
EDIT: In my opinion, Python is a great first language. When I was first starting off with it, I found the MIT OpenCourseWare class very useful. One very important note: the class is taught using Python 2.x instead of 3.x so some of the given code won't work right for you. Even if you don't watch all the video lectures, the assignments they give are of a reasonable difficulty and the reading assignments reference some excellent python learning materials.
The Udacity CS101 class also offers a good, directed introduction to programming in Python (and also uses Python 2.x) but I only worked through about half of the assignments there. I'd still recommend taking a look at it, however.

Related

wrong answer for large input

I am trying to determine whether an integer can be expressed in the form of a^b where b>1 and the given integer is greater than 0. My code runs fine for all test cases except for one.
It gives wrong answer for the following input:
536870912
I cant understand why.
def isPower(self, A):
if(A==1):
return (1)
for i in range(2,int(A**0.5)+1):
val=log(A,i)
if(int(val)-val==0):
return (1)
else:
return (0)
This will solve:
from math import log
def isPower(A):
if(A==1):
return (1)
if (A&-A)==(A):
return (1)
for i in range(2,int(A**0.5)+1):
val=log(A,i)
if(int(val)-val==0):
return (1)
else:
return (0)
If you are looking for reason on why it is not working please refer the below link:
Dealing with accuracy in Python math operations

Running unit tests on a non OOP code without any return value

I have a script of this form which is called in a program (from another similar function). I need to use unittest module to write tests for this function.
It doesn't exactly return anything but changes a lot of globals
It takes inputs
I can't change it to an OOP code right now
I want to test cases where I change a certain global varible and see if ,let's say, TOTFRAC is positive or something.
I have read tests for OOP codes where I call each variable as an object parameter, but what do I do if my code isn't Object Oriented.
Note: I have removed a lot of lines of code because it is rather long, so things might not exactl make sense
import numpy
import math
def SETUP(LAST):
def GOTO999():
print(' ERROR IN GAS INPUT : NGAS=',NGAS,'\n')
for J in range(1,6):
# print(J)
print(' N=',J,' NGAS=',NGASN[J],' FRAC=',FRAC[J])
LAST=1
return
# A lot of globals
# Initialising variables
NBREM=[]
EBRTOT=[]
for K in range(1,6):
NBREM.append(0)
EBRTOT.append(0.0)
NGAS=int(input('NGAS'))
NEVENT=int(input('NEVENT'))
IMIP=int(input('IMIP'))
NDVEC=int(input('NDVEC'))
NSEED=int(input('NSEED'))
ESTART=float(input('ESTART'))
ETHRM=float(input('ETHRM'))
ECUT=float(input('ECUT'))
ICOUNT=0
if(IMIP == 1):
ICOUNT=1
if(NGAS == 0):
LAST=1
return
if(ESTART > 3.0*(10**6) and IMIP == 3):
print(' SUBROUTINE STOPPED: X-RAY ENERGY=','%.3f' % ESTART,'EV. MAXIMUM ENERGY 3.0MEV')
sys.exit()
if(IMIP != 1 and NEVENT > 10000):
print(' SUBROUTINE STOPPED: NUMBER OF EVENTS =',NEVENT,' LARGER THAN ARRAY LIMIT OF 10000')
sys.exit()
NGASN=[]
for i in range(1,6):
NGASN.append(int(input('NGASN'+str(i))))
FRAC=[]
for i in range(1,6):
FRAC.append(round(float(input('FRAC')),4))
TEMPC=round(float(input('TEMPC')),4)
TORR=round(float(input('TORR')),4)
# more inputs
if(IWRITE != 0):
outputfile=open("DEGRAD.OUT","w")
EBIG=0.05*ESTART/1000.
EFINAL=ESTART*1.0001+760.0*EBIG/TORR*(TEMPC+ABZERO)/293.15*EFIELD
if(EFINAL < (1.01*ESTART)):
EFINAL=1.01*ESTART
# CHECK INPUT
TOTFRAC=0.00
if(NGAS == 0 or NGAS > 6):
GOTO999()
for J in range(1,NGAS):
print('J',J)
if(NGASN[J]== 0 or FRAC[J] == 0.00):
GOTO999()
TOTFRAC=TOTFRAC+FRAC[J]
if(abs(TOTFRAC-100.00)> 1*(10**-6)):
print(TOTFRAC)
GOTO999()
if(NDVEC): #22594
PHI=0
THETA=0
elif(NDVEC==-1):
PHI=0
THETA=numpy.arccos(-1)
elif(NDVEC==0):
PHI=0.0
THETA=API/2.0
elif(NDVEC==2):
R3=DRAND48(0.0,1.0)
PHI=TWOPI*R3
R4=DRAND48(1.5, 1.9)
THETA=numpy.arccos(1.0-2.0*R4)
else :
print('DIRECTION OF BEAM NOT DEFINED NDVEC =',NDVEC)
sys.exit()
if(NSEED != 0):
RM48(NSEED,0,0)
CORR=ABZERO*TORR/(ATMOS*(ABZERO+TEMPC)*100.00)
GOTO999()
# end
As #hoefling has pointed out, the code as it is now is hardly testable. But, this is not because it is not object oriented. You can easily test non-object oriented code as long as it has a suitable structure. Which means, break long functions down into smaller ones, use function arguments and return values rather than global variables etc. - none of this has anything to do with OOP. In fact, your code violates many coding principles that were known and formulated long before OOP was en vogue (1974), see https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style.
I recommend reading one or some of the following books:
Code Complete by Steve McConnell - a classic book about how to write great code.
Refactoring by Martin Fowler - how to migrate from not-so-great code to better code.
Clean Code by Robert C. Martin - again, how to write great code.

Wrapper Function in Python

#***This code uses wrapper function to print the phone number in a
standard format with country code (if not supplied in the input)***
def ori_func(a):
mm=[]
def wraap(*args):
for k in args:
for i in k:
#print(i)
if len(str(i))==10:
mm.append("+91"+str(i))
elif str(i)[0]=="0" and len(str(i))==11:
mm.append("+91"+str(i)[1:])
#elif len(str(i))==12 and i[0]=="+":
# mm.append(i)
elif len(str(i)) == 12:
mm.append("+"+str(i))
#print (mm)
return a(mm)
return wraap
#ori_func
def srt_phone(mm):
#sorted(int(mm))
for j in sorted(mm):
cc=str(j)[:3]
mmn1=str(j)[3:8]
mmn2=str(j)[8:]
print (cc+" "+mmn1+" "+mmn2)
m=[1234567891, 912345678923, +919876543219,"07418529637"]
srt_phone(m)
This code works fine as per my knowledge. However I need you to look-through my code and let me know my level of Wrapper function knowledge is correct
When I pass a list to wrapper function, do I need to really use 2 "For" loops in wrapper function like I did? Is there any other way?
When we asked to get the phone number as input in INT format,how to handle with the input that starts with 0?
Thanks
Yes. There are other ways but that way is pretty clean.
You can't, and I suggest not treating phone numbers as numbers because they aren't real numbers. Real numbers can't start with a + or a 0.
Your code looks fine to me; I'd have done a few things differently but that's just personal preference. I do recommend that you look into using #functools.wraps(a) on your inner function.

assert function in python

For a given code:
pattern = r'(?:some_pattern)'
def find(seq):
ret = []
while True :
m= pattern_re.match(seq)
if not m :
break
myseq= m.group(2)
assert len(myseq)%3 == 0
assert len(myseq) > 6
ret.append(myseq)
pos = m.end()
return ret
sequence = 'some sequence'
my_seq = find(sequence)
this returns ret in which only first assert function is taken and not the second . Any solution for it ?
the question simply is how to make code consider both the assert function
For starters, why are you using assert?
As soon as the first assert fails an AssertionError is raised and execution of the program stops.
You should be using normal conditionals. Besides that, there is so much wrong with or unusualy with this code I seriously suggest you to read the Python tutorial at http://docs.python.org/tutorial/
Pointers:
print statement after return
usage of assert instead of conditionals
the unnecessary while loop
no proper indenting
Furthermore you pasted an example that plainly does not execute since the indenting is wrong and the function called on the last line does not exist in your code. Please be more precise if you want help :-)

Python. Project Euler Q35. Got a solution but I don't understand why other method doesn't work.

def rot_dig(x):
y=''
output=[x]
listing=list(x)
for i in range(1,len(x)):
listing.append(listing[0])
del(listing[0])
for i in listing:
y=y+i
output.append(y)
y=''
return output
import math
def prime_is(x,prime):
for m in prime:
if m&lt=math.sqrt(x):
if x%m==0:
return False
else:
return True
prime=[2]
for x in range(3,1000000):
if prime_is(x,prime):
prime.append(x)
primestr=[]
for x in prime:
primestr.append(str(x))
sums=0
for x in primestr:
count=0
for y in rot_dig(x):
if y in primestr:
count+=1
if count==len(x):
sums+=1
else:
for y in rot_dig(x):
if y in primestr:
primestr.remove(y)
print sums
When run with the bold code the solutions miss the final rotation. So if it looks at say 1193, it includes 1193, 3119, 9311 but not 1931. I have spent a while trying to work out why but I don't get it.
I have since edited the code to make it much quicker and solved the problem I had by simply removing the block of code, but I can't understand why it happens since surely that block of code will only be executed on non circular primes.
It's probably because your outer loop is for x in primestr: and the marked code removes items from primestr. You don't want to change primestr while looping over it that way. You could use a loop like while i < len(primestr) instead.
Some other improvements would be to compute sqrt outside the loop; to use a list comprehension instead of a loop to create primestr; and especially to use string slicing in rot_dig, it's way more complicated than it needs to be.

Categories