Algorithm 整数的范围是否至少包含一个完全平方?
给定两个整数Algorithm 整数的范围是否至少包含一个完全平方?,algorithm,math,integer,square-root,Algorithm,Math,Integer,Square Root,给定两个整数a和b,是否有一种有效的方法来测试是否存在另一个整数n,从而a≤n2错误 intervalContainsSquare(5,9)=>false(注意:9在此间隔之外) intervalContainsSquare(9,9)=>false(此间隔为空) intervalContainsSquare(4,9)=>true(4在此间隔内) intervalContainsSquare(5,16)=>true(9在此间隔内) intervalContainsSquare(1,10)=>tru
a
和b
,是否有一种有效的方法来测试是否存在另一个整数n
,从而a≤n2错误
intervalContainsSquare(5,9)
=>false(注意:9在此间隔之外)
intervalContainsSquare(9,9)
=>false(此间隔为空)
intervalContainsSquare(4,9)
=>true(4在此间隔内)
intervalContainsSquare(5,16)
=>true(9在此间隔内)
intervalContainsSquare(1,10)
=>true(1,4和9都在此间隔内)
找到sqrt(a)和sqrt(b)的组成部分,比如sa和sb
如果sa2=a,则输出是
如果sb2=b和sa=sb-1,则输出no
如果sa
其他输出号
您可以对上述内容进行优化,以消除sqrt(b)的计算(类似于JDunkerly的答案)
或者你想避免计算a和b的平方根吗
通过使用类似于二进制搜索的方法,可以完全避免计算平方根
从n的猜测开始,n=1,然后计算n2
考虑如果a如果你接受计算两个平方根,因为它的单调性,你有这个不等式,它相当于你的起始不等式:
sqrt(a) <= n < sqrt(b)
sqrt(a)
得到较低数字的平方根并将其四舍五入
取较大数字的平方根并向下取整
如果1小于或等于2,就会有一个完美的正方形
获取较低数字的平方根。如果这是一个整数,那么就完成了。
否则,将数字四舍五入并平方。如果这小于b,则为真
这样你只需要计算一个平方根
为了避免a等于b的问题,您应该首先检查它。因为这种情况总是错误的。据我所知,计算一个数字是否是平方并不比在硬情况下计算它的平方根快。事实上,你可以做一个预计算,知道它不是一个正方形,这可能会平均节省你的时间
同样,对于这个问题,您可以进行预计算以确定sqrt(b)-sqrt(a)>=1,这意味着a和b之间的距离足够远,它们之间必须有一个正方形。对于某些代数,这个不等式等价于(b-a-1)^2>=4*a的条件,或者如果你想让它以更对称的形式出现,(a-b)^2+1>=2*(a+b)。所以这个预计算可以不用平方根,只用一个整数乘积和一些加法和减法
如果a和b几乎完全相同,那么您仍然可以使用查看低阶二进制数字作为预计算的技巧,以知道它们之间没有平方。但它们必须靠得很近,这样的预计算可能不值得
如果这些预计算是不确定的,那么除了其他所有人的解之外,我想不出任何其他的方法,一种方法是使用牛顿的方法来找到forb
。然后,您可以检查该数字是否在范围内。我怀疑它比简单调用平方根函数快,但它肯定更有趣:
int main( int argc, char* argv[] )
{
int a, b;
double xk=0, xk1;
int root;
int iter=0;
a = atoi( argv[1] );
b = atoi( argv[2] );
xk1 = b / 32 + 1; // +1 to ensure > 0
xk1 = b;
while( fabs( xk1 - xk ) >= .5 ) {
xk = xk1;
xk1 = ( xk + b / xk ) / 2.;
printf( "%d) xk = %f\n", ++iter, xk1 );
}
root = (int)xk1;
// If b is a perfect square, then this finds that root, so it also
// needs to check if (n-1)^2 falls in the range.
// And this does a lot more multiplications than it needs
if ( root*root >= a && root*root < b ||
(root-1)*(root-1) >= a && (root-1)*(root-1) < b )
printf( "Contains perfect square\n" );
else
printf( "Does not contain perfect square\n" );
return 1;
}
intmain(intargc,char*argv[])
{
INTA,b;
双xk=0,xk1;
int根;
int-iter=0;
a=atoi(argv[1]);
b=atoi(argv[2]);
xk1=b/32+1;//+1以确保>0
xk1=b;
而(晶圆厂(xk1-xk)>=0.5){
xk=xk1;
xk1=(xk+b/xk)/2。;
printf(“%d)xk=%f\n”,++iter,xk1);
}
根=(int)xk1;
//如果b是一个完美的正方形,那么它会找到根,所以它也是
//需要检查(n-1)^2是否在范围内。
//这做的乘法比它需要的多得多
如果(root*root>=a&&root*root=a&&(根-1)*(根-1)
除了JDunkerley不错的解决方案(+1),还有一个可能的改进需要测试并用于计算整数平方根为什么希望完全避免平方根?甚至在你找到解决这个问题的最有效方法之前,你已经看到了只需要2个平方根的方法。这是在O(1)时间内完成的,所以在我看来,任何您希望进行的改进都需要花费比节省计算时间更多的时间来思考。我错了吗?如果违反了@duffymo:butn^2
部分,则您的第三个示例不正确,因为9不小于9。@Amadan:a≤ n²=4ab@Eyal“你能解释一下你是怎么得出这个公式的吗?”亚当,格雷格描述得很快
int main( int argc, char* argv[] )
{
int a, b;
double xk=0, xk1;
int root;
int iter=0;
a = atoi( argv[1] );
b = atoi( argv[2] );
xk1 = b / 32 + 1; // +1 to ensure > 0
xk1 = b;
while( fabs( xk1 - xk ) >= .5 ) {
xk = xk1;
xk1 = ( xk + b / xk ) / 2.;
printf( "%d) xk = %f\n", ++iter, xk1 );
}
root = (int)xk1;
// If b is a perfect square, then this finds that root, so it also
// needs to check if (n-1)^2 falls in the range.
// And this does a lot more multiplications than it needs
if ( root*root >= a && root*root < b ||
(root-1)*(root-1) >= a && (root-1)*(root-1) < b )
printf( "Contains perfect square\n" );
else
printf( "Does not contain perfect square\n" );
return 1;
}