I must write a function that computes the logarithm of a number x relative to a base b (rounded down if the answer is not an integer). I wrote this function but it's not working
def myLog(x, b):
result = 1
if b > x :
result -= 1
return result
elif x == b :
return result
else :
result += 1
b *= result
return myLog(x,b)
Why are you multiplying the base by result and changing the base? When you determine that the base fits into the input number, you should be dividing the number by the base. Since the division means the final number is 1 more, you add 1 to the result of the recursive call.
def myLog(x, b):
result = 1
if b > x:
result -= 1
return result
elif x == b:
return result
else:
x /= b
return 1 + myLog(x, b)
Example: myLog(32, 2):
32/2 = 16, add 1 to answer
16/2 = 8, add 1 to answer
...
answer = 5
Some of the code is unnecessary though, and I would further edit it to be this:
def myLog(x, b):
if b > x:
return 0
elif x == b:
return 1
else:
x /= b
return 1 + myLog(x, b)
Related
I need help for defining the fibanocci 2 function. The fibanocci 2 function is decribed as :
fib2(n) = {0 if n <= 0, 1 if n = 1, 2 if n = 2, ( fib2( n - 1) * fib2( n - 2)) - fib2( n - 3) else}
We need to define this function iterative.
I tried my best but i couldn't write a working code.
def fib2(n: int) -> int:
if n <= 0:
return 0
elif n == 1:
return 1
elif n == 2:
return 2
else:
n = ((n - 1) * (n - 2) - (n - 3)
return n
a = fib2(7)
print (a)
assert (fib2(7) == 37)
the output from this fib2 function is 26 but it should be 37.
Thank you in advance
For the iterative version you have to use a for loop.
And just add the 3 previous numbers to get the next one.
Here is a piece of code:
def fib3(n):
a = 0
b = 1
c = 0
for n in range(n):
newc = a+b+c
a = b
b = c
c = newc
return newc
print(fib3(7))
assert (fib3(7) == 37)
You can not change the value of a parameter.
Please try to return directly :
Return ((fb2(n-1)×fb2(n-2))-fb2(n-3))
So it will work as a recursive function.
def fibo(n):
current = 0
previous_1 = 1
previous_2 = 0
for i in range(1,n):
current = previous_1 + previous_2
previous_2 = previous_1
previous_1 = current
return current
To do it iteratively, the best way is to write it on paper to understand how it works.
Mathematically fibo is Fn = Fn-1 + Fn-2 . Therefore, you can create variables called previous_1 and previous_2 which represents the elements of Fn and you simply update them on each run.
Fn is current
My recursive function doesn't seem to be working - it’s supposed to take parameters a and b and return
a^b.
Here it is:
def power(a, b):
If b == 0:
return
return a * power(a, b-1)
power(2, 3)
Base case return statement is null. You should return 1 (since a^0 = 1 for a != 0).
if b == 0:
return 1
You might want to handle the case for a = 0 separately though, since 0^0 is mathematically undefined:
if a == 0:
if b > 0:
return 0
else
# raise an exception here?
def power(a, b):
if b == 0:
return 1;
return a * power(a, b - 1);
class Solution(object):
def getSum(self, a, b):
if (a == 0):
return b
if (b == 0):
return a;
while(b != 0):
_a = a ^ b
_b = (a & b) << 1
a = _a
b = _b
return a
But when one of a, b < 0 or both, how the script should be like?
+ operator internally makes a call to __add__(). So, you may directly call a.__add__(b) to get sum. Below is the modified code:
>>> class Solution(object):
... def getSum(self, a, b):
... return a.__add__(b)
...
>>> s = Solution()
>>> s.getSum(1, 2)
3
OR, you may use operator.add(a, b) as:
>>> import operator
>>> operator.add(1, 2)
3
I enjoy solving other people's problems.
class Solution(object):
def getSum(self, a, b):
return sum([a, b])
Edit: If you are in for some fantasy. You can do operator overloading.
class CrappyInt(int):
def __init__(self, num):
self.num = num
def __eq__(self, a):
return self.__add__(a)
m = CrappyInt(3)
n = CrappyInt(4)
print m == n
# 7
This maybe a little hard for you now. But it is fun.
You can also use operator package
import operator
class Solution(object):
def getSum(self, a, b):
return operator.add(a, b)
And if you want to hassle with binary bitwise operations. Here is first method:
def complex_add_1(x, y):
while y != 0:
b = x & y
x = x ^ y
y = b << 1
return x
And here is the another one with recursion:
def complex_add_2(x, y):
if y == 0:
return x
else:
return complex_add_2(x ^ y, (x & y) << 1)
Edit: methods with bitwise operations are working only in Python 3
My old highschool program that I found on my usb stick. Yes it's crude but it works.
def s(a,b):
a = bin(a)[2:]
b = bin(b)[2:]
c_in = 0
value = ''
if not len(a) == len(b):
to_fill = abs(len(a) - len(b))
if len(a) > len(b):
b = b.zfill(len(a))
else:
a = a.zfill(len(b))
for i,j in zip(reversed(a),reversed(b)):
i_xor_j = int(i) ^ int(j)
i_and_j = int(i) and int(j)
s = int(c_in) ^ int(i_xor_j)
c_in_and_i_xor_j = int(c_in) and int(i_xor_j)
c_in = int(i_and_j) or int(c_in_and_i_xor_j)
value += str(int(s))
value += str(int(c_in))
return int(value[::-1],2)
print(s(5,9))
#>> 14
Or I would have see if I could cheat with sum.
This was kinda fun :) I'm not sure if this is what you're after, but these all should work so long as you're using integers
def subtract(a, b):
if a < 0:
return negative(add(negative(a), b))
if b < 0:
return add(a, negative(b))
if a < b:
return negative(subtract(b, a))
if b == 0:
return a
return subtract(a^b, (~a & b) << 1)
def negative(a):
if a == 0: return 0
a = ~a
b = 1
while b > 0:
a, b = a^b, (a&b) << 1
return a
def add(a, b):
if a < 0:
return negative(subtract(negative(a), b))
if b < 0:
return subtract(a, negative(b))
if b == 0:
return a
return add(a^b, (a & b) << 1)
def multiply(a, b):
if a == 0 or b == 0:
return 0
if b < 0:
a = negative(a)
b = negative(b)
A = 0
while b > 0:
A = add(A, a)
b = subtract(b, 1)
return A
def div(a, b):
if b == 0:
raise ZeroDivisionError
if a == 0:
return 0
if b < 0:
a = negative(a)
b = negative(b)
A = 0
if a < 0:
while a < 0:
a = add(a, b)
A = subtract(A, 1)
else:
while b < a :
a = subtract(a, b)
A = add(A, 1)
return A
def mod(a, b):
return subtract(a, multiply(div(a, b),b))
negation by two's compliment is used to get a function where a and b are both greater than 0 and the correct operation (addition or subtraction) is selected. further with subtraction, care is taken to not yield a negative result. This is done because the recursive definitions of add and subtract hate crossing 0. Also in this case the recursive add and subtract do the exact same thing as your loop.
I've written this function to calculate sin(x) using Taylor series to any specified degree of accuracy, 'N terms', my problem is the results aren't being returned as expected and I can't figure out why, any help would be appreciated.
What is am expecting is:
1 6.28318530718
2 -35.0585169332
3 46.5467323429
4 -30.1591274102
5 11.8995665347
6 -3.19507604213
7 0.624876542716
8 -0.0932457590621
9 0.0109834031461
What I am getting is:
1 None
2 6.28318530718
3 -35.0585169332
4 46.5467323429
5 -30.1591274102
6 11.8995665347
7 -3.19507604213
8 0.624876542716
9 -0.0932457590621
Thanks in advance.
def factorial(x):
if x <= 1:
return 1
else:
return x * factorial(x-1)
def sinNterms(x, N):
x = float(x)
while N >1:
result = x
for i in range(2, N):
power = ((2 * i)-1)
sign = 1
if i % 2 == 0:
sign = -1
else:
sign = 1
result = result + (((x ** power)*sign) / factorial(power))
return result
pi = 3.141592653589793
for i in range(1,10):
print i, sinNterms(2*pi, i)
I see that you are putting the return under the for which will break it out of the while loop. You should explain if this is what you mean to do. However, given the for i in range(1,10): means that you will ignore the first entry and return None when the input argument i is 1. Is this really what you wanted? Also, since you always exit after the calculation, you should not do a while N > 1 but use if N > 1 to avoid infinite recursion.
The reason why your results are off is because you are using range incorrectly. range(2, N) gives you a list of numbers from 2 to N-1. Thus range(2, 2) gives you an empty list.
You should calculate the range(2, N+1)
def sinNterms(x, N):
x = float(x)
while N >1:
result = x
for i in range(2, N):
Your comment explains that you have the lines of code in the wrong order. You should have
def sinNterms(x, N):
x = float(x)
result = x
# replace the while with an if since you do not need a loop
# Otherwise you would get an infinite recursion
if N > 1:
for i in range(2, N+1):
power = ((2 * i)-1)
sign = 1
if i % 2 == 0:
sign = -1
# The else is not needed as this is the default
# else:
# sign = 1
# use += operator for the calculation
result += (((x ** power)*sign) / factorial(power))
# Now return the value with the indentation under the if N > 1
return result
Note that in order to handle things set factorial to return a float not an int.
An alternative method that saves some calculations is
def sinNterms(x, N):
x = float(x)
lim = 1e-12
result = 0
sign = 1
# This range gives the odd numbers, saves calculation.
for i in range(1, 2*(N+1), 2):
# use += operator for the calculation
temp = ((x ** i)*sign) / factorial(i)
if fabs(temp) < lim:
break
result += temp
sign *= -1
return result
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.