如何有效地找到小于给定的int n的最大平方数(即4、9、16)? 我有以下尝试:
int square = (int)Math.sqrt(number);
return square*square;
但是,仅求平方就具有平方根的效率很低。
en.wikipedia.org/wiki/Square_number可能有帮助
与stackoverflow.com/questions/4930307/几乎相同
@hatchet不,要点是我不想要整数部分。我想直接去平方号。
需要s /小于n /不大于n / g才能使代码正确。
找到整数平方根(使用有效的整数平方根算法,而不是Maths浮点sqrt),然后对它求平方,您就可以找到所需的内容。
@hatchet你甚至读过我的问题吗?那正是我已经做过的。我要求其他东西。
@Deduplicator看起来很粗略,但是int-> double转换是精确的,并且Math.sqrt保证正确地四舍五入,因此可以进行错误分析以表明我们永远不会正确舍入到整数(这是唯一的)截断可能出错的方式)。
@DavidGrinberg-我链接到的问题中的整数平方根与您的问题中使用的浮点平方根有区别。
在查询表中进行斐波那契搜索? (对于32位int,只有2 ^ 16平方)尽管sqrt并不慢。
上下文是什么?如果您试图为循环找到极限,则最好将i * i < n作为循环终止而不是i < precalculated_square_root。否则,在现代硬件上,浮动平方根可能与您将获得的速度一样快。
预先说明:应该注意,能够将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之下的平方。
这会比平方根的本地实现更快吗?
@AndyTurner使用双倍?使用以sqrt作为指令或其他拐杖的处理器?也许是,也许不是。 :)-但是,在其他所有条件相同的情况下,整数运算速度更快。
@laune:基准测试或仅仅是个轶事。整数算术使用较少的门,但是如果您拥有足够的芯片空间,那么它本质上并不会更快。实际上,在现代处理器上,浮点除法可能比整数除法要快。
@rici尽管如此,术语"整数算术"仍不应以原始的CPU指令时序来理解:浮点数算法往往需要更多代码,例如,用于确定何时停止迭代或到/从的转换。串。同样,某些优化只能用整数算术完成,例如,i / 2 vs. f / 2.0,或i ++ vs. f + 1.0。较短的代码,较少的缓存行...但是,当(如此处)一条FP指令完成大部分工作时,所有替代方案都可以搁置。
有一个牛顿算法可以找到平方根,在给定的链接中,您需要的是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=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=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
线性时间算法:
int largestSquare(int n) {
int i = 0;
while ((i+1)*(i+1) < n) {
++i;
}
return i*i;
}
如果这比找到平方根更快,我会感到非常惊讶。
我也是。但是您说过您不想使用平方根。不使用平方根的感觉就像是微优化。
绝对是微优化。那就是我要的。这根本不是优化
您要针对什么进行优化?例如结果的查找表在时间方面非常有效,但是存储起来很麻烦。
您可以通过二进制搜索执行相同的操作...