Algorithm 完美平方算法-实现说明
这个问题是这里帖子的后续内容: 其中一个帖子有这样一个解决方案,可以确定给定的数字是否是完美的正方形:Algorithm 完美平方算法-实现说明,algorithm,integer,square-root,perfect-square,Algorithm,Integer,Square Root,Perfect Square,这个问题是这里帖子的后续内容: 其中一个帖子有这样一个解决方案,可以确定给定的数字是否是完美的正方形: public final static boolean isPerfectSquare(long n) { if (n < 0) return false; switch((int)(n & 0xF)) { case 0: case 1: case 4: case 9:
public final static boolean isPerfectSquare(long n)
{
if (n < 0)
return false;
switch((int)(n & 0xF))
{
case 0: case 1: case 4: case 9:
long tst = (long)Math.sqrt(n);
return tst*tst == n;
default:
return false;
}
}
public最终静态布尔值isPerfectSquare(长n)
{
if(n<0)
返回false;
开关((int)(n&0xF))
{
案例0:案例1:案例4:案例9:
longtst=(long)Math.sqrt(n);
返回tst*tst==n;
违约:
返回false;
}
}
这是一个简洁的解决方案,效果非常好。但是,对于它是如何工作的,或者更重要的是,这个解决方案是如何导出的,没有详细解释。
我想知道这个解决方案是如何推导出来的。
n&0xF
只选取n的最后4位,因为0xF
是二进制的1111
。实际上,这相当于n除以16得到余数
该算法利用了这样一个事实:m
,m%16
只能是0
,1
,4
或9
中的一个。可以证明如下:
任何自然数n
都可以表示为4k
、4k+1
、4k+2
或4k+3
(对于某些自然数k
)
然后,n^2
可以是(4k)^2
,(4k+1)^2
,(4k+2)^2
或(4k+3)^2
。
=>n^2
可以是16k^2
,16k^2+8k+1
,16k^2+16k+4
或16k^2+24k+9
如果n^2
是16k^2
,n^2%16
显然是0
如果n^2
是16k^2+8k+1
,n^2%16=(8k+1)%16=(8k%16)+1=0或9,这取决于k
是偶数还是奇数
如果n^2
是16k^2+16k+4
,n^2%16=4
如果n^2
是16k^2+24k+9
,n^2%16=(24k+9)%16=(16k+8k+9)%16=1或9,这取决于k是奇数还是偶数
因此,n^2%16
只能是0,1,4或9
虽然这个问题与编程无关,但它仍然与选择的解决方法有关。这就是为什么我会发布正确的解释。显然,x&0xF
只相当于x%16
——即从除法到16的模(因为is将保留相应的位。然而,此技巧仅适用于2的幂次方)
此方法基于完美正方形的非常重要的一点:
如果整数K
除以模r
的任何整数b
(因此K%b=r
),那么K2和r2除以b
将得到相同的模。
为什么??实际上,我们有:K2-r2=(K-r)(K+r)和K-r
将被除以b
,结果为整数(因为r
是K
除以b
的模)
这就是为什么b=16
:
r r^2 (r^2)%16
0 ----> 0 ---> 0
1 ----> 1 ---> 1
2 ----> 4 ---> 4
3 ----> 9 ---> 9
4 ---> 16 ---> 0
5 ---> 25 ---> 9
6 ---> 36 ---> 4
7 ---> 49 ---> 1
8 ---> 64 ---> 0
9 ---> 81 ---> 1
10 --> 100 ---> 4
11 --> 121 ---> 9
12 --> 144 ---> 0
13 --> 169 ---> 9
14 --> 196 ---> 4
15 --> 225 ---> 1
r^2(r^2)%16
0 ----> 0 ---> 0
1 ----> 1 ---> 1
2 ----> 4 ---> 4
3 ----> 9 ---> 9
4 ---> 16 ---> 0
5 ---> 25 ---> 9
6 ---> 36 ---> 4
7 ---> 49 ---> 1
8 ---> 64 ---> 0
9 ---> 81 ---> 1
10 --> 100 ---> 4
11 --> 121 ---> 9
12 --> 144 ---> 0
13 --> 169 ---> 9
14 --> 196 ---> 4
15 --> 225 ---> 1
因此,正如您所看到的,如果r
是从完美平方的除得到的,那么模必须与r^2%16
的模相同-因此,它只能是0
,1
,4
和9
还有一件事很重要:这是完美平方的必要条件,而不是足够的条件(所以要点是“如果模不是0,1,4或9,那么数不是完美平方”,但它仍然不等于“如果模是0,1,4或9,那么数就是完美平方”简单示例是17
:17%16=1
,但17不是完美的正方形)这就是为什么即使满足模条件,该方法仍然使用
返回tst*tst==n
-i、 e.通过计算其平方根来测试n
是否为完美平方。因此,这种方法大约在4倍的时间内会更快——因为对于12的16个可能的模,我们总是可以返回false
如果一个数字是一个完美的平方,它的平方根就是一个整数。所以你只要取平方根。由于浮点算术是不准确的,您不需要检查平方根是否为整数,只需将其四舍五入到最接近的整数,然后检查该整数是否为数字的平方根。这似乎利用了一个事实,即完美平方除以16只能有0、1、4或9作为余数。数学网站可能更适合解释为什么会出现这种情况。@凯文,在这种情况下,用穷举法证明(列举所有15个案例)就足够了。请注意,平方的最低有效位仅受其根的最低有效位的影响。这让我隐约想起素数的轮分解。这是一种快速的方法,可以消除那些不是优秀候选人的优秀候选人。可以用它来做这个,是的(事实上是这样)。实际上,因式分解的情况也依赖于必要条件(显然,这仍然是不够的),您忘记了显示16k^2+16k+4%16=4。所以你的答案应该是,n^2%16只能是0,14或9。