找到小于n的最大平方数的算法

时间:2015-02-07 18:03:01

标签: java algorithm math square-root

如何有效地找到小于给定int n的最大平方数(即4,9,16)?我有以下尝试:

int square = (int)Math.sqrt(number);
return square*square;

但它有一个明显的低效率,即获得一个平方根,只是为了我们可以对它进行平方。

3 个答案:

答案 0 :(得分:2)

预先:应该注意的是,能够将sqrt作为机器指令的处理器将足够快。毫无疑问,它的(微)程序使用Newton-Raphson,并且该算法具有二次收敛性,每次迭代时精确数字的数量加倍。

所以,像这样的想法并不值得追求,尽管它们使用了正方形等不错的属性(参见下一个提案)

// compute the root of the biggests square that is a power of two < n
public static int pcomp( int n ){
  long p2 = 1;
  int i = 0;
  while( p2 < n ){
    p2 <<= 2;
    i += 2;
  }
  p2 >>= 2;
  i -= 2;
  return (int)(p2 >>= i/2);
}

public static int squareLowerThan( int n ){
  int p = pcomp(n);
  int p2 = p*p;     // biggest power of two that is a square < n 
  int d = 1;        // increase using odd numbers until n is exceeded
  while( p2 + 2*p + d < n ){
    p2 += 2*p + d;
    d += 2;
  }
  return p2;
}

但我确信牛顿的算法更快。二次收敛,记住。

public static int sqrt( int n ){
  int x = n;
  while( true ){
    int y = (x + n/x)/2;
    if( y >= x ) return x;
    x = y;
  }
}

返回整数平方根。返回x * x得到n下方的正方形。

答案 1 :(得分:1)

线性时间算法:

int largestSquare(int n) {
  int i = 0;
  while ((i+1)*(i+1) < n) {
    ++i;
  }
  return i*i;
}

答案 2 :(得分:1)

有一个牛顿算法可以找到平方根,在给定的链接中你需要的是m ^ 2而不是m

https://math.stackexchange.com/questions/34235/algorithm-for-computing-square-root-of-a-perfect-square-integer

即使你想直接找到方形而不是找到m,我也不认为它比这更快。

在这里工作代码

public static int squareLessThanN(int N)
{
        int x=N;
        int y=(x+N/x)/2;
        while(y<x)
        {
               x=y;
               y=(x+N/x)/2;
        }
        return x*x;
 }

但似乎内置的平方根似乎更快。刚刚测量了两者的运行时间。

class Square{
        public static void main(String[] args)
        {
                long startTime = System.currentTimeMillis();
                System.out.println(squareLessThanN(149899437943L));
                long endTime   = System.currentTimeMillis();
                long totalTime = endTime - startTime;
                System.out.println("Running time is "+totalTime);

                startTime = System.currentTimeMillis();
                System.out.println(normal(149899437943L));
                endTime   = System.currentTimeMillis();
                totalTime = endTime - startTime;
                System.out.println("Running time is "+totalTime);

        }
        public static long squareLessThanN(long N)
        {
                long x=N;
                long y=(x+N/x)/2;
                while(y<x)
                {
                        x=y;
                        y=(x+N/x)/2;
                }
                return x*x;
        }
        public static long normal(long N)
        {
                long square = (long)Math.sqrt(N);
                return square*square;
        }
}

输出

149899060224
Running time is 1
149899060224
Running time is 0