0

I have written the following code. I am trying to avoid conditionals or while. How would computer know that it should run the loop for that many times.?. Means, is there any way range function would have the value automatically? Like for example if one is looking for sqrt of 2000, the following code won't work as range function specified from 5 to 10. I am almost there, i am just missing something?

Specifying range is not solving the problem

def fun():       
    fG = n/2
    for i in range(5,10):
        g = (0.5) * (fG + (n/fG))
        fG = g
VietHTran
  • 2,233
  • 2
  • 9
  • 16
Abid Raza
  • 9
  • 4

2 Answers2

0

I am not sure of exactly what you are trying to achieve, but if I correctly understand, the following code should address what you are looking for:

Solution

import numpy as np # need this to test the custom
                   # defined function SQRT()
                   # against numpy's sqrt() function.
# err_epsilon = the acceptable error for stopping the loop.
def SQRT(n, err_epsilon = 1e-8):       
    fg = n/2
    fG = fg + 1
    while abs(fg-fG)>err_epsilon:
        fg = fG
        fG = (0.5) * (fG + (n/fG))
    return 0.5*(fG+fg)

# Test against numpy.sqrt()
SQRT(2), np.sqrt(2)

Result:

Note that we had err_epsilon=1e-8 and so should have correct square-root calculated up to 8 places after the decimal. And the following results conform to that: 1.41421356. In fact they are the same up to the 11-th place after the decimal.

(1.4142135623738925, 1.4142135623730951)

An Option

Since, you prefer avoiding a while and/or conditionals, you may consider using the following. But, you can not possibly stop the loop without a conditional step that evaluates when to stop calculations. The implementation given above makes use of the conditional and a while (as you do not know a priori how many loops it would take to get to the accepted level of error-threshold.

You are actually not using the variable i in the for loop. And hence, it is best to discard its value, should you decide to use the for loop with the range function.

def fun(n, start = 0, stop = 10, step = 1):       
    fG = n/2
    # we skip saving the variable generated 
    # from the range iterator.
    for _ in range(start,stop,step):
        fG = (0.5) * (fG + (n/fG))
    return fG

Square-root Algorithm

Assuming you are trying to find square-root, I would encourage you to take a look at these:

  1. Square Root with Babylonian Algorithm: Python Implementation [1]
  2. Writing your own square root function
  3. Finding the square root using Newton's method (errors!). Important.
  4. Python Implementation of Square Root with Newton's Method
  5. Newton Square Root Method in Python

Quoting [1] as-is:

def BabylonianAlgorithm(number):
    if(number == 0):
        return 0;

    g = number/2.0;
    g2 = g + 1;
    while(g != g2):
        n = number/ g;
        g2 = g;
        g = (g + n)/2;

    return g;
print('The Square root of 0.3 =', BabylonianAlgorithm(0.3));
CypherX
  • 7,019
  • 3
  • 25
  • 37
  • I could be wrong in understanding your question though. If that is the case, please add some more explanation with expected results and we can work on a viable solution. – CypherX Sep 16 '19 at 03:32
0

First of all, I'm not sure why you decided on for i in range(5, 10) when you never use the variable i. This is equivalent to for _ in range(10).

Secondly, it sounds like you're asking how to know what the correct number of iterations are. First of all, you need to understand that there are a lot of numbers for which newtons method will never return an exact answer, so you need to decide how much precision you want.

Once you're precision oriented, you can change your code from:

def fun(n, iterations):       
    fG = n/2
    for i in range(iterations):
        g = (0.5) * (fG + (n/fG))
        fG = g
    return g

To something where you measure how much the measurement has changed since the last iteration:

def fun2(n, delta):       
    fG = n/2
    iters = 0
    while True:
        g = (0.5) * (fG + (n/fG))
        if abs(fG - g) < delta:
            return g, iters
        fG = g
        iters += 1

Then you can specify a good analogue of how close you want to be to the true value:

fun2(2000,1) # (44.72230608683239, 6)
fun2(2000, 0.001) # (44.7213595600124, 7)
fun2(2000, 0.000000000000001) # (44.721359549995796, 9)
Turksarama
  • 1,136
  • 6
  • 13