Chained comparison number range in Python - python

I have the following function:
def InRange(number):
return 5 <= number >= 1
I want this to say false if the number is not within the range of 1 to 5 using a chain comparison, but cannot seem to get this right.
Any suggestions?

You want it like this:
def InRange(number):
return 1 <= number <= 5
Note that you could also do:
def InRange(number):
return 0 < number < 6

Use this:
1 <= number <= 5
From docs:
x < y <= z is equivalent to x < y and y <= z, except that y is
evaluated only once (but in both cases z is not evaluated at all when
x < y is found to be false).
Your (incorrect)expression is actually equivalent to:
number >=5 and number >= 1
So, it is going to be True for any number between 1 to infinity:

Alternatively you can do (it seemed appropriate based on the function's name):
def InRange(number):
return number in range(1, 6)
For large numbers you should use:
def InRange(number):
return number in xrange(1, 10000000)

Related

How do I go about coding a custom function (without using any library) which returns the log of a number in python [duplicate]

I need to generate the result of the log.
I know that:
Then I made my code:
def log(x, base):
log_b = 2
while x != int(round(base ** log_b)):
log_b += 0.01
print(log_b)
return int(round(log_b))
But it works very slowly. Can I use other method?
One other thing you might want to consider is using the Taylor series of the natural logarithm:
Once you've approximated the natural log using a number of terms from this series, it is easy to change base:
EDIT: Here's another useful identity:
Using this, we could write something along the lines of
def ln(x):
n = 1000.0
return n * ((x ** (1/n)) - 1)
Testing it out, we have:
print ln(math.e), math.log(math.e)
print ln(0.5), math.log(0.5)
print ln(100.0), math.log(100.0)
Output:
1.00050016671 1.0
-0.692907009547 -0.69314718056
4.6157902784 4.60517018599
This shows our value compared to the math.log value (separated by a space) and, as you can see, we're pretty accurate. You'll probably start to lose some accuracy as you get very large (e.g. ln(10000) will be about 0.4 greater than it should), but you can always increase n if you need to.
I used recursion:
def myLog(x, b):
if x < b:
return 0
return 1 + myLog(x/b, b)
You can use binary search for that.
You can get more information on binary search on Wikipedia:
Binary search;
Doubling search.
# search for log_base(x) in range [mn, mx] using binary search
def log_in_range(x, base, mn, mx):
if (mn <= mx):
med = (mn + mx) / 2.0
y = base ** med
if abs(y - x) < 0.00001: # or if math.isclose(x, y): https://docs.python.org/3/library/math.html#math.isclose
return med
elif x > y:
return log_in_range(x, base, med, mx)
elif x < y:
return log_in_range(x, base, mn, med)
return 0
# determine range using doubling search, then call log_in_range
def log(x, base):
if base <= 0 or base == 1 or x <= 0:
raise ValueError('math domain error')
elif 0 < base < 1:
return -log(x, 1/base)
elif 1 <= x and 1 < base:
mx = 1
y = base
while y < x:
y *= y
mx *= 2
return log_in_range(x, base, 0, mx)
elif 0 <= x < 1 and 1 < base:
mn = -1
y = 1/base
while y > x:
y = y ** 0.5
mn *= 2
return log_in_range(x, base, mn, 0)
import math
try :
number_and_base = input() ##input the values for number and base
##assigning those values for the variables
number = int(number_and_base.split()[0])
base = int(number_and_base.split()[1])
##exception handling
except ValueError :
print ("Invalid input...!")
##program
else:
n1 = 1 ##taking an initial value to iterate
while(number >= int(round(base**(n1),0))) : ##finding the most similer value to the number given, varying the vlaue of the power
n1 += 0.000001 ##increasing the initial value bit by bit
n2 = n1-0.0001
if abs(number-base**(n2)) < abs(base**(n1)-number) :
n = n2
else :
n = n1
print(math.floor(n)) ##output value
Comparison:-
This is how your log works:-
def your_log(x, base):
log_b = 2
while x != int(round(base ** log_b)):
log_b += 0.01
#print log_b
return int(round(log_b))
print your_log(16, 2)
# %timeit %run your_log.py
# 1000 loops, best of 3: 579 us per loop
This is my proposed improvement:-
def my_log(x, base):
count = -1
while x > 0:
x /= base
count += 1
if x == 0:
return count
print my_log(16, 2)
# %timeit %run my_log.py
# 1000 loops, best of 3: 321 us per loop
which is faster, using the %timeit magic function in iPython to time the execution for comparison.
It will be long process since it goes in a loop. Therefore,
def log(x,base):
result = ln(x)/ln(base)
return result
def ln(x):
val = x
return 99999999*(x**(1/99999999)-1)
log(8,3)
Values are nearly equal but not exact.

Reversing an integer using recursion in Python

While practicing recursion I came across a question to reverse an integer using recursion. I tried to do the question without converting the integer into a string.
I was able to solve the question partially but the output would always come without any of the zeroes from the original input. Below is the code I came up with:
def reverseNumber(n):
if (n//10) == 0:
return n
lastDigit = n%10
ans = reverseNumber(n//10)
nod = 0
for i in str(ans):
nod += 1
return (10**nod)*lastDigit + ans
Upon inspection I could see that this was happening because when lastDigit is 0 it only returned the reversed integer from the recursive call i.e input 4230 will give 324.
But this also meant that all zeroes between the original input would also get removed as we went deeper in the recursive calls.
So please tell me how to modify this code so that zeroes in the original input are not removed while reversing.
You probably need just this:
def rev(n):
if n>0:
return str(n%10)+rev(n//10)
else:
return ''
reverseNumber should return an int and accept positive and negative numbers.
The simplest way to fix your code, without handling negative numbers, is:
def reverseNumber(n):
if n == 0:
return 0
lastDigit = n%10
n //= 10
return int(str(lastDigit) + str(reverseNumber(n))) if n else lastDigit
for test in (0, 123, 120):
print(test, reverseNumber(test))
Prints:
0 0
123 321
120 21
Yes! The reverse of 120 is 21 when you are dealing with int types as opposed to str types.
Another implementation that does handle negative numbers takes a whole different approach:
I have broken this out into two functions. Function rev is a generator function that assumes that it is being called with a positive, non-negative number and will recursively yield successive digits of the number in reverse. reverseNumber will join these numbers, convert to an int, adjust the sign and return the final result.
def reverseNumber(n):
def rev(n):
assert n >= 0
yield str(n % 10)
n //= 10
if n != 0:
yield from rev(n)
if n == 0: return 0 # special case
x = int(''.join(rev(abs(n))))
return x if n >= 0 else -x
tests = [0, 132, -132, 120]
for test in tests:
print(test, reverseNumber(test))
Prints:
0 0
132 231
-132 -231
120 21
For all non-negative n, when n < 10 it is a single digit and already the same as its reverse -
def reverse(n = 0):
if n < 10:
return str(n)
else
return str(n%10) + rev(n//10)
you can also try the following Python3 code. It will cover positive and negative integers to be reversed as integers - not as strings ...
x = int(input("What integer shall be reversed? "))
n = abs(x) # ... to handle negative integers
r = 0 # ... will hold the reversed int.
while n > 0: # Recursion part reversing int.
r = (r * 10) + (n % 10) # using '%' modulo
n = int(n / 10) # and a 'dirty way' to floor
if x < 0: # Turn result neg. if x was neg.
return (r * -1)
else:
return r # Keep result pos. if x was pos.
This approach will leave your zeros in the middle of the integer intact, though it will make any zero at the end of the initial number vanish - rightfully so as integers do not start with a zero. ;))

Python: Is there a way to print even numbers within an unknown range and without if statement?

I have a homework to do in Python class and was given this question:
Make a program that gets 2 numbers from the user, and prints all even
numbers in the range of those 2 numbers, you can only use as many for
statements as you want, but can't use another loops or if statement.
I understand that I need to use this code:
for num in range (x,y+1,2):
print (num)
but without any if statements, I can't check if the value x inserted is even or odd, and if the user inserted the number 5 as x, all the prints will be odd numbers.
I also tried to enter each number to a tuple or an array, but I still can't check if the first number is even to start printing.
def printEvenFor(x,y):
evenNumbers =[]
for i in range (x,y+1):
evenNumbers.append(i)
print (evenNumbers[::2])
or
def printEvenFor(x,y):
for i in range (x,y+1,2):
print(i,",")
I expect the output of printEvenFor(5,12) to be 6,8,10,12 but it is 5,7,9,11
You can make x even, by using floor division and then multiplication:
x = (x // 2) * 2
x will then be rounded to the previous even integer or stay the same if it was even before.
If you want to round it to the following even integer you need to do:
x = ((x + 1) // 2) * 2
This can be improved further by using shifting operators:
x = (x >> 1) << 1 #Alternative 1
x = ((x + 1) >> 1) << 1 #Alternative 2
Examples:
#Alternative 1
x = 9
x = (x >> 1) << 1
#x is now 8
#Alternative 2
x = 9
x = ((x + 1) >> 1) << 1
#x is now 10
The second one is probably more suitable for you
You can use reminder to get the correct range:
def print_event_for(min_, max_):
reminder = min_ % 2
for i in range(min_+reminder, max_+reminder, 2):
print(i)
print_event_for(5, 12)
Output:
6
8
10
12
one way is by using while, that takes the start and end range in
for each in range(int(input()),int(input())):
while each%2 == 0:
print (each)
break;
Try this:
x = x+x%2
for num in range (x,y+1,2):
print (num)
You can do it this way:
>>> for n in range((x + 1) // 2 * 2, y+1, 2):
print(n)
The first argument to range forces it to be the next even number if it is odd. The last argument goes up in twos.
The following function will do what you want. I use round to force the boundaries to be even in order to get start the range on an even number.
def print_even_between(x, y):
x = round(x / 2) * 2
y = round(y / 2) * 2
for i in range(x, y, 2):
print(i)
print(y)
Hacky but fun: multiplying strings with zero.
>>> low, high = int(input()), int(input())
5
13
>>> for n in range(low, high + 1):
... print('{}\n'.format(n)*(not n%2), end='')
...
6
8
10
12
Odd numbes are not printed because the string is multiplied with False (acting as zero).
def printEvenfor(x,y):
return list(range(((x+1) // 2) * 2,y+1, 2))
printEvenfor(9,16)

Difficulty with listing function

Write a function named "counting" that takes a list of numbers as a parameter and returns the number of values in the input that are between 29.88 and 48.05 not including these end points. (My code below)
def counting(number):
sum = 0
for x in number:
if (29.88 < x < 48.05):
sum = sum + x
return sum
How do I return the number of values in the input instead of the first number of an input?
your return statement is indented too deep; you should return it after the for loop. also sum is not a good name as it is a built-in function that you overwrite.
and you should add 1 to the sum (you are counting) and not x itself.
you could also try this using the built-in function sum:
def counting(number):
return sum(29.88 < x < 48.05 for x in number)
(this is actually short for sum(1 for x in number if 29.88 < x < 48.05) and works because True is basically 1 and False is basically 0).
Or to be similar to yours:
def counting(number):
c = 0
for x in number:
if 29.88 < x < 48.05:
c += 1
return c
Or can do one-liner, len:
def counting(number):
return len([29.88 < x < 48.05 for x in number])
You could also use filter() on your list to keep only elements that the given function evaluates to true.
def counting(number):
return len(list(filter(lambda x: 29.88 < x < 48.05, number)))

Python prime number generator prints out every number

I made this prime number generator but it just prints every number (1, 2, 3...).
I am aware that there are other questions about this but I don't understand any of them. Here is what I have so far:
x = 1
y = 1
while x >= y:
if x % y == 0:
print(x)
x = x + 1
y = 1
else:
y = y + 1
y = 1
From your question, I think, it would be better try this way :
n = 10
i = 2
while i < n :
prime = 1 # reset the `prime` variable before the inner loop
for a in range(2, i):
if i%a == 0:
prime = 0
break
if prime:
print (i)
i += 1
Output :
2
3
5
7
There's something called a rubber ducky test where you explain your code, step by step, to a rubber duck. It forces you to walk through every step and you'll often find the error. In this case, think about what y is when you do x%y. You'll see that y=1 the first time this is called. So it will iterate through the loop incrementing x by 1 and y will remain set it 1. And x%y when y=1 will always be...

Categories

Resources