I have a function called check defined like so
def check(n):
if n > 17325551999:
return True
return False
which is always returning true. eg
>check(1000000000)
True
>check(5)
True
Can anyone give me some insight as to why this is happening? Is it because the number is larger than the largest possible int?
edit: I've added a picture of my python prompt.
Updated answer:
From your screenshot it is clear you didn't post the same code here as what you are actually running:
def check(num):
if n > 17325551999:
return True
return False
either raises a NameError for 'n' or tests n as a global if it is defined. The actual parameter to the function is called num, and is completely ignored in the function.
In other words, you'd have to assign to the n global to make your version work.
The fix is to test the right parameter:
def check(num):
return num > 17325551999
Previous answer before the screenshot was posted:
You are not passing in integers. With integers your code works just fine:
>>> def check(n):
... if n > 17325551999:
... return True
... return False
...
>>> check(5)
False
Instead you are probably passing in strings instead:
>>> check('5')
True
In Python 2, numbers always sort before strings (a mistake remedied in Python 3), so any number is always going to be 'smaller' than a string:
>>> '0' > 0
True
Avoid this problem by making sure your function is called with an integer argument, or explicitly convert n in the function:
def check(n):
return int(n) > 17325551999:
Note that the > operator already returns True or False, no need to use if here.
Related
Code
def addition(num):
if num:
return num + addition(num - 1)
else:
return 0
res = addition(10)
print(res)
Explanation
I know what the function is doing:
it is a recursive function
I just don't know what if num: means or the else part.
I am guessing it means as long as the num is int do what is inside the if, else return 0.
Question
Can someone tell me what this code means?
if variable: and truthyiness
See the boolean values and Python's Truth Value Testing:
What is Truthy and Falsy? How is it different from True and False?
You can evaluate truthy and falsy values using the bool() conversion-function:
print('None:', bool(None))
print('zero:', bool(0))
print('negative:', bool(-1))
print('positive:', bool(1))
if num: mets if num is defined and unequal to 0:
is defined: num is not None
and is not zero: num != 0
bool(0) is False. The opposite condition is tested by if not num.
The role of if in a recursive function
It's a recursive function which calls itself until exit-condition num == 0 is met in the else branch. Then it simply returns 0. So, the role of if num: is the continue-condition opposed to an exit-condition.
You could also write it as exit-condition:
def addition(num):
if not num: # equivalent to: if num == 0 or num is None
return 0 # return 0 if exit-condition met
# default behavior: recurse until zero met
return num + addition(num - 1)
See also:
recursive factorial function
Basics of recursion in Python
Edge-cases for input
Note, how input of None and other falsy values return a zero.
Please also consider the edge-case of negative input, as Fred commented. Could (silently) return 0 to abort addition. Also might raise an error to warn about misuse, like:
if num < 0:
raise ValueError("Can not calculate the recursive-sum for negative values.")
What happens if a float like 10.5 is given as input?
It would step through each -1 decrease until 0.5. The next call of addition(-0.5) would jump over the num == 0 exit-condition and cause infinite recursion, even a stackoverflow.
Python and many other languages have a concept of "falsy", which roughly means "values that are treated as False when evaluated as a boolean". In Python, values that are falsy include empty collections such as empty lists, strings, sets, tuples, and dicts, the int or float 0, and None. I may be missing some here, and you may find that some classes are designed to be treated as falsy as well under certain conditions. There are also "truthy" values which evaluate to True is a boolean context. It's easy to find out if a value is truthy or falsy. Simply call bool() on it:
bool(0.0)
# False
In the context of your code, when 0 is reached, that will be evaluated as falsy, triggering the exit condition.
if num: means if num is different than 0 : if num!=0.
you better remove the else statement.
def addition(num): if num: return num + addition(num - 1) return 0
python already knows that return is an else statement.
here's a playlist of one of the bests on youtube by corey to learn & become at python : https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTskrapNbzXhwoFUiLCjGgY7
and also I recommend this book, automating the boring stuff with python. it's free : https://automatetheboringstuff.com/
def greater(list, num)
for x in list:
if x > num:
return True
else:
return False
as you can see in my code, i am trying to write a function that return True if list_number contained number that is bigger than second argument, otherwise return False.
but here is confusing:
when i input: greater([1, 2, 3], 2), and its return False. I am wondering why is that? the first argument contained 3 and its bigger than 2.
any helps and explanations will be appreciated.
You want to have it return at the end of the function. Right now, you have it return after checking only the first number. Try this:
def has_gt(list_number,number):
for x in list_number:
if x > number:
return True
return False
A property of if/else is that if one runs, the other doesn't. But in both cases, one runs. In your code, this snippet:
if x > number:
return True
else:
return False
Means that it will check if the number is bigger than the number in question. If it is, it will return True. If not, it will return False. A return call instantly ends the processing of a function, so it will stop checking after that.
To summarize, your code loops through the target list. It checks the first number, one, and sees if it is bigger than two. It is not, so the code returns False, instantly ending the function. So, your function just ended in a False, which is what it returned.
The change I made was that it returns False at the end of the code. This means that it will check each value for being greater than the target. If it finds any value greater than the target, it will end processing, with a return value of True. If the code hasn't returned by the time it reaches the end of the function, it will return False because of the statement at the end of the function.
Actually what happens is the else part also runs just after comparing the number (here 2) with the first element in the list_number (here 1) thus returns false.
So the solution is you need to let the for loop first run completely which is stopped by the else statement.
def has_gt(list_number,number):
for x in list_number:
if x > number:
return True
return False
The function is all_even in which you input an int and it returns bool. It returns true if all the digits are even. e.g. all_even(2224) gives true and all_even(1362) gives false.
I wrote the code but it is not working properly.
This is what I have:
def is_very_even(num: int) -> bool:
even = False
strnum = str(num)
for ch in strnum:
if int(ch)% 2==0:
even = True
return even
The code gives true even if the num has a single even num and the rest are odd e.g all_even(231) is true which is supposed to be false. Can somebody tell me what is wrong with it.
You could use a recursive approach (without converting to a string):
def allEven(N): return True if N==0 else N%2==0 and allEven(N//10)
output:
allEven(246) # True
allEven(123) # False
Note that the issue with your function is that you set even to True as soon as you encounter an even digit. If there is an odd digit after that, your even variable remains True. This will tell you that "at least one" digit is even, not that they are all even.
You are checking if all the numbers are even. So first assume that it's true, all the numbers are even and set even = True. Then check if there is any odd number in the string. If there is, then set even = False
Now, if there is any odd number in the string, even will be False and therefore we can verify it.
def is_very_even(num: int) -> bool:
even = True
strnum = str(num)
for ch in strnum:
if int(ch)% 2 !=0:
even = False
return even
This code can also be improvised like this. We don't need to keep checking if we found a single odd number. We can just return false immediately. And if all the numbers checks out but none returns false, then it must be an all even string.
def is_very_even(num: int) -> bool:
for ch in str(num):
if int(ch)% 2 !=0:
return False
return True
I would solve it like this:
def is_very_even(s) -> bool:
return all(int(x) % 2 == 0 for x in str(s))
This converts every character to an integer and checks if it is even with modulo. This is processed in a so called generator expression.
Then we use the builtin all method to check if the generator delivers only True values.
In this code:
def is_even(x):
if x == 0:
return True
else:
return is_odd(x-1)
def is_odd(x):
return not is_even(x)
print(is_even(2))
print(is_odd(2))
I keep going through this in my head and wondering how it's working. It seems to me that eventually x in is_even(x) will return True every time. However, when I run the code, it works perfectly fine and returns True and False appropriately. Can someone explain how that's happening?
I understand the basic concept of recursion and fully understand how the famous factorial example works. However, this one is hard for me to wrap my head around.
Feeling inept right now...
It always helps to decompose a recurrence relation till you find its base case.
is_even(2) => return is_odd(1)
=> return not is_even(1)
=> return not is_odd(0)
=> return not not is_even(0)
=> return not not True
=> return True ---- (1)
is_odd(2) => return not is_even(2)
=> return not True [from (1)]
=> return False
In general, from your recurrence functions, it is easy to observe that is_even(n) will return [not not not ... n times] True, while is_odd(n) will return [not not not ... n - 1 times] True. So the number of nots and hence the final expression depend on n (aha!). Well, that's certainly a roundabout way of asking whether
n % 2 == 0
Add a couple of print statements and you will see what it is doing:
from __future__ import print_function
def is_even(x):
if x == 0:
print('True')
return True
else:
return is_odd(x-1)
def is_odd(x):
print('not', end=' ')
return not is_even(x)
>>> is_even(5)
not not not not not True
False
>>> is_odd(5)
not not not not not not True
True
Like in most cases it might be helpful to include simply prints to follow the execution:
def is_even(x):
print('check if {} is even'.format(x))
if x == 0:
return True
else:
return is_odd(x-1)
def is_odd(x):
print('check if {} is odd'.format(x))
return not is_even(x)
Then in your cases:
>>> print(is_even(2))
check if 2 is even
check if 1 is odd
check if 1 is even
check if 0 is odd
check if 0 is even
True
>>> print(is_odd(2))
check if 2 is odd
check if 2 is even
check if 1 is odd
check if 1 is even
check if 0 is odd
check if 0 is even
False
So basically it decrements the number until it's 0. The point is just how many nots have been accumulated in the is_odd calls. If it's an even number of nots then the result will be True, otherwise False.
That's true; the recursion is supposed to end inside is_even.
And when that will happen, you'll know that the number you have is 0.
Now lets go backwards. This final state will be achieved by two cases - direct call to is_even(0) or a call from is_odd(0). In the first case - the result is all good. In the second - the result will be returned to the is_odd function, negated, and therefore will be falsy - giving a correct result.
Now, here the missing piece comes - the recursion: in order to reach this state, we need to decrease the argument each time, passing it through the opposite function - and that's exactly what we get with return is_odd(x-1).
Note: eventually this recursion leads to a chain of negations of the value True returned by the is_even. This chain is of length x where x is your number, and therefore odd or even in correspondence.
Therefore, the following code will do the same (lacking the is_odd nice side effect):
def is_even (x):
res = True
while x:
res = not res
x -= 1
return res
I think that all the other answers are great but potentially the easiest way to understand the problem is how many times the answer will get "not"ed. Every time it passes through the is_odd function a not will be added on to the final answer. True will always be returned but for even numbers, there will always be an even number of nots which cancel each other out, but for odd numbers they will always have an odd number of nots and therefore return false.
s="(8+(2+4))"
def checker(n):
if len(n) == 0:
return True
if n[0].isdigit==True:
if n[1].isdigit==True:
return False
else:
checker(n[1:])
else:
checker(n[1:])
This is what I have so far. Simple code, trying to see if a string meets the following conditions.
However when i perform checker(s) i get:
True
IndexError: string index out of range
Any help? Thanks in advance
Edit: The function's purpose is to produce true if the string contains only single digit numbers, and false if 2 or more-figured digits exist in the string.
When the length of n is 0, the n[0] part is going to raise an error because the string in empty. You should add a return statement there instead of print.
def checker(n):
if len(n) < 2:
return True
if n[0] in x:
Note that the conditions must be len(n) < 2 otherwise you'll get an error on n[1] when the length of string is 1.
Secondly you're trying to match characters to a list which contains integers, so the in checks are always going to be False. Either convert the list items to string or better use str.isdigit.
>>> '1'.isdigit()
True
>>> ')'.isdigit()
False
>>> '12'.isdigit()
True
Update:
You can use regex and all for this:
>>> import re
def check(strs):
nums = re.findall(r'\d+',strs)
return all(len(c) == 1 for c in nums)
...
>>> s="(8+(2+4))"
>>> check(s)
True
>>> check("(8+(2+42))")
False
Working version of your code:
s="(8+(2+4))"
def checker(n):
if not n: #better than len(n) == 0, empty string returns False in python
return True
if n[0].isdigit(): #str.digit is a method and it already returns a boolean value
if n[1].isdigit():
return False
else:
return checker(n[1:]) # use return statement for recursive calls
# otherwise the recursive calls may return None
else:
return checker(n[1:])
print checker("(8+(2+4))")
print checker("(8+(2+42))")
output:
True
False
You should do return True after the first if statement, not print True. The function continues to run after that statement and hits an error when the input is size 0.
I can't reproduce your error.
I had to fix a few things:
Indentation, which I'm guessing was just a problem pasting into the page
.isdigit() is a function; calling .isdigit==True is going to compare a function object with True, which is never going to be true. I changed .isdigit==True to .isdigit()
I made sure return value gets bubbled up - without this, the recursion completes okay but the outermost function just returns "None".
Aside from that, a few print statements show that this is working as expected
s="(8+(2+4))"
t="(8+(20+4))"
def checker(n):
print "checking %s" % n
if len(n) == 0:
print "Returning true"
return True
if n[0].isdigit():
if n[1].isdigit():
print "returning false"
return False
else:
return checker(n[1:])
else:
return checker(n[1:])
print checker(s)
print checker(t)
Output:
checking (8+(2+4))
checking 8+(2+4))
checking +(2+4))
checking (2+4))
checking 2+4))
checking +4))
checking 4))
checking ))
checking )
checking
Returning true
True
checking (8+(20+4))
checking 8+(20+4))
checking +(20+4))
checking (20+4))
checking 20+4))
returning false
False