I am trying to do square root using newton-raphson algorithm of random numbers given by this formula:
a = m * 10 ^c
where m is random float in range (0,1) and c is random integer in range (-300,300).
Code i wrote works perfectly with precision of root as 0.01 and c in range (-30,30) but freezes or returns wrong results when i use c range given in task.
here is code for newton function
def newton_raphson(a):
iterations_count = 0
x_n_result = a/2
while abs(x_n_result - a / x_n_result) > 0.01:
x_n_result = (x_n_result + a/x_n_result)/2
iterations_count = iterations_count + 1
if x_n_result*x_n_result == a:
break
iterations.append(iterations_count)
results.append(x_n_result)
print("Result of function", x_n_result)
return
and part where numbers to root are randomized
for i in range(0, 100):
m = random.uniform(0, 1)
c = random.randint(-30, 30)
a = m * 10 **c
random_c.append(c)
numbers.append(a)
print("Number to root : ", i, "|", a, '\n')
newton_raphson(a)
plot of the amount of iteration from the value of c
plt.bar(random_c, iterations, color='red')
Script is supposed to root 100 random numbers and then plot amount of iteration required to root number from values of c. Problem is like i said before with proper range of c value. I believe it has to do something with range of variables. Any sugestion how to solve this?
First observation is that your logic will get you a square root, not a cubic root.
The second thing is that your random numbers can contain negative values which will never converge for a square root.
If you really wanted a cubic root, you could do it like this:
def cubic(number):
result = number
while abs(number/result/result - result) > 0.01:
result += (number/result/result - result)/2
return result
you could also approach this in a generic fashion by creating a newton/raphson general purpose function that takes a delta function as parameter to use on a number parameter:
def newtonRaphson(delta,n):
result = n
while abs(delta(n,result)) > 0.01:
result += delta(n,result)/2
return result
def cubic(n,r): return n/r/r - r
def sqrt(n,r): return n/r - r
The use the newtonRaphson method with your chosen delta function:
newtonRaphson(sqrt,25) # 5.000023178253949
newtonRaphson(cubic,125) # 5.003284700817307
Related
I am trying to create a code that returns a approximation of pi given n iterations that the user will give. The higher n the more accurate.
I created a while loop to do this, and it works fine:
import math
x = 1
k = 0
n = int(input("Enter n:"))
while x <= n:
k=k+(1/x**2) # summation of 1/k**2 for every n times
y=k*6 # multiply k by 6 like in formula
fin = math.sqrt(y) # find sqrt of y like in the formula
x += 1
print(fin)
But now I'm trying to make this into a function. This is what I've come up with:
import math
def pi(n):
x = 1
k = 0
#n = int(input("Enter n:"))
while x <= n:
k=k+(1/x**2) # summation of 1/k**2 for every n times
y=k*6 # multiply k by 6 like in formula
fin = math.sqrt(y) # find sqrt of y like in the formula
x += 1
return fin
g=pi(int(input("Enter n:")))
print(g)
For some reason I get different answers... why is it when I use the function that the answer becomes inaccurate?
You have your return inside the loop, hence the block inside the while is executed only once and the rest of approximations are never calculated, put your return out of your cycle:
while x <= n:
k=k+(1/x**2) # summation of 1/k**2 for every n times
y=k*6 # multiply k by 6 like in formula
fin = math.sqrt(y) # find sqrt of y like in the formula
x += 1
return fin
I tested it, now it returns the same result with both approaches.
Have a good day! :D
Problem Statement :
Construct a building which will be a pile of n cubes. The cube at the bottom will have a volume of n^3, the cube above will have volume of (n-1)^3 and so on until the top which will have a volume of 1^3.
You are given the total volume m of the building. Being given m can you find the number n of cubes you will have to build?
The parameter of the function findNb (find_nb, find-nb, findNb) will be an integer m and you have to return the integer n such as n^3 + (n-1)^3 + ... + 1^3 = m if such a n exists or -1 if there is no such n.
Below code is correct mathematically and would calculate correct value but would fails when submitted on codewars. The message says if it takes more than 12 seconds on their servers to execute, it requires more optimization. Thank you for your help.
def find_nb(m):
# your code
n = int(m**(1./3.))
#print (n)
total_volume = 0
for i in range (1,n+1):
#print (i*i*i)
total_volume+= i*i*i
#print (total_volume)
if(total_volume == m):
#print (i)
return i
break
return -1
You should try to use some maths. Typically, the sum of k^3 for k=1 to n is (n(n+1)/2)^2.
So
def find_nb(m):
i=0
while int((i(i+1)/2)**2) < m:
i += 1
if ((i(i+1)/2)^2) == m:
return(i)
return(-1)
This is probably not the best solution, but you should try it, as it enables to avoid a loop.
I have this sample quiz question but not to sure how to approach it with while loops.
Implement the nearest_square function. The function takes an integer argument limit, and returns the largest square number that is less than limit.
A square number is the product of an integer multiplied by itself, for example 36 is a square number because it equals 6*6.
There's more than one way to write this code, but I suggest you use a while loop!
Here is a test case you can copy to test your code. Feel free to write additional tests too!
test1 = nearest_square(40)
print("expected result: 36, actual result: {}".format(test1))
I have managed to solve it. Thank you.
def nearest_square(limit):
limit = limit ** (0.5)
y = int (limit)
while y < limit :
y = y*y
return y
test1 = nearest_square(40)
print("expected result: 36,actual result:{}".format(test1))
Try using the following method to return the nearest square given the limit parameter:
def nearest_square(limit):
answer = 0
while (answer+1)**2 < limit:
answer += 1
return answer**2
Normally, it's more efficient to approach this kind of questions mathematically (maybe not for low inputs but certainly yes for pretty big numbers). That said, we have a good tool at hand: the square root.
If computing the square root of any number, n, yields a double value whose decimal part is fully composed by zeroes then your number is a perfect square (square of an integer).
Interestingly (and this is more related to your question), if you choose another number (that is not a perfect square) and apply a rounding operation (floor or ceil) you'll get the closest square (lower or bigger).
An example:
n = 24
sqrt = math.sqrt(n) # sqrt(24) = 4.898979485566356...
closest = [math.floor(sqrt)**2, math.ceil(sqrt)**2] # closest = [16, 25]
this is how i did it with while loop:
def nearest_square(value):
i = 2
while i < value:
square = i*i
if square == value:
return square
i+=1
value-=1
print (nearest_square(40))
def nearest_square(value):
i = 1
result = 1
while (result < value):
if (result == value):
return result
i+=1
result = i*i
return (i-1)*(i-1)
print (nearest_square(82))
Here is my code:
`
def nearest_square(limit):
while limit > 3:
i = 2
while i <= limit//2:
square = i*i
if square == limit:
return square
else:
i += 1
limit -= 1
return 1
`
Here's what i did.
def nearest_square(limit):
y = 0
while y**2 < limit:
y+=1
if y**2 == limit:
return(y)
return(y-1)
print(nearest_square(40))
Here is my implementation of it.
this one is with while loop
def near1(limit):
i = 1
square = 1
while (i*i) < limit:
square = i*i
i = i+1
return square
but the easiest one is below.
Simple math and modulo
import math
def near(limit):
i = int(math.pow(limit, .5))
return i*i
This is what i did.
import math
def nearest_square(limit):
a = math.sqrt(limit)
while type(a) != type(int()):
limit -=1
return limit
I was curious if any of you could come up with a more streamline version of code to calculate Brown numbers. as of the moment, this code can do ~650! before it moves to a crawl. Brown Numbers are calculated thought the equation n! + 1 = m**(2) Where M is an integer
brownNum = 8
import math
def squareNum(n):
x = n // 2
seen = set([x])
while x * x != n:
x = (x + (n // x)) // 2
if x in seen: return False
seen.add(x)
return True
while True:
for i in range(math.factorial(brownNum)+1,math.factorial(brownNum)+2):
if squareNum(i) is True:
print("pass")
print(brownNum)
print(math.factorial(brownNum)+1)
break
else:
print(brownNum)
print(math.factorial(brownNum)+1)
brownNum = brownNum + 1
continue
break
print(input(" "))
Sorry, I don't understand the logic behind your code.
I don't understand why you calculate math.factorial(brownNum) 4 times with the same value of brownNum each time through the while True loop. And in the for loop:
for i in range(math.factorial(brownNum)+1,math.factorial(brownNum)+2):
i will only take on the value of math.factorial(brownNum)+1
Anyway, here's my Python 3 code for a brute force search of Brown numbers. It quickly finds the only 3 known pairs, and then proceeds to test all the other numbers under 1000 in around 1.8 seconds on this 2GHz 32 bit machine. After that point you can see it slowing down (it hits 2000 around the 20 second mark) but it will chug along happily until the factorials get too large for your machine to hold.
I print progress information to stderr so that it can be separated from the Brown_number pair output. Also, stderr doesn't require flushing when you don't print a newline, unlike stdout (at least, it doesn't on Linux).
import sys
# Calculate the integer square root of `m` using Newton's method.
# Returns r: r**2 <= m < (r+1)**2
def int_sqrt(m):
if m <= 0:
return 0
n = m << 2
r = n >> (n.bit_length() // 2)
while True:
d = (n // r - r) >> 1
r += d
if -1 <= d <= 1:
break
return r >> 1
# Search for Browns numbers
fac = i = 1
while True:
if i % 100 == 0:
print('\r', i, file=sys.stderr, end='')
fac *= i
n = fac + 1
r = int_sqrt(n)
if r*r == n:
print('\nFound', i, r)
i += 1
You might want to:
pre calculate your square numbers, instead of testing for them on the fly
pre calculate your factorial for each loop iteration num_fac = math.factorial(brownNum) instead of multiple calls
implement your own, memoized, factorial
that should let you run to the hard limits of your machine
one optimization i would make would be to implement a 'wrapper' function around math.factorial that caches previous values of factorial so that as your brownNum increases, factorial doesn't have as much work to do. this is known as 'memoization' in computer science.
edit: found another SO answer with similar intention: Python: Is math.factorial memoized?
You should also initialize the square root more closely to the root.
e = int(math.log(n,4))
x = n//2**e
Because of 4**e <= n <= 4**(e+1) the square root will be between x/2 and x which should yield quadratic convergence of the Heron formula from the first iteration on.
I’m having a bit of trouble controlling the results from a data generating algorithm I am working on. Basically it takes values from a list and then lists all the different combinations to get to a specific sum. So far the code works fine(haven’t tested scaling it with many variables yet), but I need to allow for negative numbers to be include in the list.
The way I think I can solve this problem is to put a collar on the possible results as to prevent infinity results(if apples is 2 and oranges are -1 then for any sum, there will be an infinite solutions but if I say there is a limit of either then it cannot go on forever.)
So Here's super basic code that detects weights:
import math
data = [-2, 10,5,50,20,25,40]
target_sum = 100
max_percent = .8 #no value can exceed 80% of total(this is to prevent infinite solutions
for node in data:
max_value = abs(math.floor((target_sum * max_percent)/node))
print node, "'s max value is ", max_value
Here's the code that generates the results(first function generates a table if its possible and the second function composes the actual results. Details/pseudo code of the algo is here: Can brute force algorithms scale? ):
from collections import defaultdict
data = [-2, 10,5,50,20,25,40]
target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool) # all values are False by default
T[0, 0] = True # base case
for i, x in enumerate(data): # i is index, x is data[i]
for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
for c in range(s / x + 1):
if T[s - c * x, i]:
T[s, i+1] = True
coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
# /* Base case: If we've assigned all the variables correctly, list this
# * solution.
# */
if k == 0:
# print what we have so far
print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
return
x_k = data[k-1]
# /* Recursive step: Try all coefficients, but only if they work. */
for c in range(sum // x_k + 1):
if T[sum - c * x_k, k - 1]:
# mark the coefficient of x_k to be c
coeff[k-1] = c
RecursivelyListAllThatWork(k - 1, sum - c * x_k)
# unmark the coefficient of x_k
coeff[k-1] = 0
RecursivelyListAllThatWork(len(data), target_sum)
My problem is, I don't know where/how to integrate my limiting code to the main code inorder to restrict results and allow for negative numbers. When I add a negative number to the list, it displays it but does not include it in the output. I think this is due to it not being added to the table(first function) and I'm not sure how to have it added(and still keep the programs structure so I can scale it with more variables).
Thanks in advance and if anything is unclear please let me know.
edit: a bit unrelated(and if detracts from the question just ignore, but since your looking at the code already, is there a way I can utilize both cpus on my machine with this code? Right now when I run it, it only uses one cpu. I know the technical method of parallel computing in python but not sure how to logically parallelize this algo)
You can restrict results by changing both loops over c from
for c in range(s / x + 1):
to
max_value = int(abs((target_sum * max_percent)/x))
for c in range(max_value + 1):
This will ensure that any coefficient in the final answer will be an integer in the range 0 to max_value inclusive.
A simple way of adding negative values is to change the loop over s from
for s in range(target_sum + 1):
to
R=200 # Maximum size of any partial sum
for s in range(-R,R+1):
Note that if you do it this way then your solution will have an additional constraint.
The new constraint is that the absolute value of every partial weighted sum must be <=R.
(You can make R large to avoid this constraint reducing the number of solutions, but this will slow down execution.)
The complete code looks like:
from collections import defaultdict
data = [-2,10,5,50,20,25,40]
target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool) # all values are False by default
T[0, 0] = True # base case
R=200 # Maximum size of any partial sum
max_percent=0.8 # Maximum weight of any term
for i, x in enumerate(data): # i is index, x is data[i]
for s in range(-R,R+1): #set the range of one higher than sum to include sum itself
max_value = int(abs((target_sum * max_percent)/x))
for c in range(max_value + 1):
if T[s - c * x, i]:
T[s, i+1] = True
coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
# /* Base case: If we've assigned all the variables correctly, list this
# * solution.
# */
if k == 0:
# print what we have so far
print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
return
x_k = data[k-1]
# /* Recursive step: Try all coefficients, but only if they work. */
max_value = int(abs((target_sum * max_percent)/x_k))
for c in range(max_value + 1):
if T[sum - c * x_k, k - 1]:
# mark the coefficient of x_k to be c
coeff[k-1] = c
RecursivelyListAllThatWork(k - 1, sum - c * x_k)
# unmark the coefficient of x_k
coeff[k-1] = 0
RecursivelyListAllThatWork(len(data), target_sum)