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。