xiaobaoqiu Blog

Think More, Code Less

Numberical Algorithm

数论算法

1. x*y

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * x乘以y
 * 限制:y >= 0
 *
 * 原理:         | (x*(y>>1))<<1      y偶数
 *      x * y = | x + (x*(y>>1))<<1  y奇数
 *              | 0                  y == 0
 * @param x
 * @param y
 * @return
 */
private static int doMuliply(int x, int y) {
    if (y == 0) return 0;

    int z = doMuliply(x, y >> 1);
    return NumberUtils.isEven(y) ? z << 1 : x + (z << 1);
}

2. x/y

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * x除以y
 * 限制:x > 0 ,y > 0
 *
 *              | ArithmeticException                     y == 0
 * 原理          | (0, 0)                                  x == 0
 *      x / y = | (q'<<1, r'<<1) 其中(q',r')=(x>>1)/y      x偶数
 *              | (q'<<1, r'<<1 + 1) 其中(q',r')=(x>>1)/y  x奇数
 * @param x
 * @param y
 * @return : 商,余
 */
public static Pair<Integer, Integer> doDivide(int x, int y) {
    if (y == 0) throw new ArithmeticException();

    if (x == 0) return Pair.build(0, 0);

    Pair<Integer, Integer> half = doDivide(x >> 1, y);
    int left = half.getLeft() << 1;
    int right = half.getRight() << 1;
    if (NumberUtils.isOdd(x)) right += 1;

    return (right < y) ? Pair.build(left, right) : Pair.build(left+1, right-y);
}

3. pow(x, y) % N

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * pow(x, y) % N
 * 限制:x > 0, y > 0, N > 1
 *
 * 原理:                  | (pow(x, y>>1) << 1) % N       y是偶数
 *        pow(x, y) % N =|
 *                       | x * (pow(x, y>>1) << 1) % N   y是奇数
 * @param x
 * @param y
 * @param N
 * @return
 */
public static int powerMod(int x, int y, int N){
    if(y == 0) return 1;

    int half = powerMod(x, y>>1, N);

    return NumberUtils.isEven(y) ? (half * half) % N : (x *half * half) % N;
}

4. 欧几里德GCD算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
 * GCD(x, y)
 * 限制:x > y > 0
 *
 * 原理:
 *       GCD(x, y) = GCD(y, x%y)
 *
 * @param x
 * @param y
 * @return
 */
public static int gcd(int x, int y){
    if(y == 0) return x;
    return gcd(y, x % y);
}

5. 素数测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * 素数测试
 * 限制:x > 0, K > 0
 *
 * 原理:
 * 费马定理:如果p是素数,则对任意的 1 <= a < x,有 pow(a, x-1) = 1 (mod x)
 * 这是素数的必要条件,但不是充分条件。
 * 随机选k个a,分别用费马定理去测试。
 *
 * @param x
 * @return
 */
public static boolean isPrime(int x, int K) {
    for (int i = 0; i < K; i++) {
        int a = (int)(Math.random() * x);
        if(powerMod(a, x-1, x) != 1){
            return false;
        }
    }
    return true;
}

总结: 《Algorithm》这本书我的理解,关注更多的是工业级别(或者说实用级别)的算法,这一点和算法导论不同,算法导论可以说是学院派,这个是工程师派。 比如上面的素数测试,这本书利用多次费马定理,从而降低误判概率(理论上还是存在误判的情况),但是正像作者说的,很多伟大的算法,都是很大概率正确的算法(而不是完全正确)。