JavaScript - Improving algorithm for finding square roots of perfect squares without Math.sqrt

China☆狼群 提交于 2020-01-13 07:01:08

问题


I'm trying to learn algorithms and coding stuff by scratch. I wrote a function that will find square roots of square numbers only, but I need to know how to improve its performance and possibly return square roots of non square numbers

function squareroot(number) {
    var number;
    for (var i = number; i >= 1; i--) {
        if (i * i === number) {
            number = i;
            break;
       }
   }
   return number;
}

 alert(squareroot(64))

Will return 8

Most importantly I need to know how to improve this performance. I don't really care about its limited functionality yet


回答1:


Here is a small improvement I can suggest. First - start iterating from 0. Second - exit loop when the square of root candidate exceeds the number.

function squareroot(number) {
    for (var i = 0; i * i <= number; i++) {
        if (i * i === number)
            return i;
   }
   return number; // don't know if you should have this line in case nothing found
}

This algo will work in O(√number) time comparing to initial O(n) which is indeed performance improvement that you asked.

Edit #1

Just even more efficient solution would be to binary search the answer as @Spektre suggested. It is known that x2 is increasing function.

function squareroot(number) {
    var lo = 0, hi = number;
    while(lo <= hi) {
         var mid = Math.floor((lo + hi) / 2);
         if(mid * mid > number) hi = mid - 1;
         else lo = mid + 1;
    }
    return hi;
}

This algo has O(log(number)) running time complexity.




回答2:


The stuff that you try to do is called numerical methods. The most rudimentary/easy numerical method for equation solving (yes, you solve an equation x^2 = a here) is a Newtons method.

All you do is iterate this equation:

In your case f(x) = x^2 - a and therefore f'(x) = 2x.

This will allow you to find a square root of any number with any precision. It is not hard to add a step which approximate the solution to an integer and verifies whether sol^2 == a




回答3:


Separates Newton's method from the function to approximate. Can be used to find other roots.

function newton(f, fPrime, tolerance) {
  var x, first;

  return function iterate(n) {
    if (!first) { x = n; first = 1; }

    var fn = f(x);

    var deltaX = fn(n) / fPrime(n);
    if (deltaX > tolerance) {
      return iterate(n - deltaX)
    }

    first = 0;
    return n;
  }
}


function f(n) { 
  return  function(x) { 
    if(n < 0) throw n + ' is outside the domain of sqrt()';
    return x*x - n;
  };
}

function fPrime(x) {
  return 2*x;
}


var sqrt = newton(f, fPrime, .00000001)
console.log(sqrt(2))
console.log(sqrt(9))
console.log(sqrt(64))



回答4:


Binary search will work best.

let number = 29;
let res = 0;

console.log((square_root_binary(number)));
function square_root_binary(number){

    if (number == 0 || number == 1)  
       return number;

    let start = 0;
    let end = number;


    while(start <= end){

        let mid = ( start + end ) / 2;

        mid = Math.floor(mid);

        if(mid * mid == number){
            return mid;
        }

        if(mid * mid < number){
            start = mid + 1;
            res = mid;
        }
        else{
            end = mid - 1;
        }
    }

    return res;
}



回答5:


function squareRoot(n){
    var avg=(a,b)=>(a+b)/2,c=5,b;
    for(let i=0;i<20;i++){
        b=n/c;
        c=avg(b,c);
    }
    return c;
}

This will return the square root by repeatedly finding the average.

var result1 = squareRoot(25) //5
var result2 = squareRoot(100) //10
var result3 = squareRoot(15) //3.872983346207417

JSFiddle: https://jsfiddle.net/L5bytmoz/12/



来源:https://stackoverflow.com/questions/35855799/javascript-improving-algorithm-for-finding-square-roots-of-perfect-squares-wit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!