費馬因式分解算法優化及素數判定


1. 費馬因式分解

1> 對於任一個奇數nn = ab = x2-y2

2> ∵ n = ab = (x+y)*(x-y)

    ∴ a = x + y, b = x-y

       x = (a+b)/2, y = (a-b)/2 (因為n為奇數,a, b必也為奇數,所以(a+b)和(a-b)必為偶數,故能被2整除,x, y為整數,x > y)

如:1 = 1*1 = 12 – 02

     3 = 3*1 = 22 – 12

     5 = 5*1 = 32 – 22

     7 = 7*1 = 42 – 32

     9 = 3*3 = 32 – 02

 

2. 費馬因式分解算法

1> y2 = x2 – n

∵ x2 – n >= y2 >= 0

∴x2 >= n, x >= sqrt(n)

∴我們可以從x = sqrt(n)開始,計算x2 – n為完全平方數即可求出x, y,然后求得a, b

 

2> python代碼

def Fermat(num):
    x = int(math.sqrt(num));
    if x*x < num:
        x += 1;
    
    #y^2 = x^2 - num
    while(True):
        y2 = x*x - num;
        y = int(math.sqrt(y2));
        if y*y == y2:
            break;
        x += 1;

    return [x+y, x-y];

 

3>. 利用完全平方數十位和個位數值性質改進費馬因式分解算法

完全平方數的最后兩個十進制數字(個位和十位)一定是下列數對之一:{00, e1, e4, 25, o6, e9}, 證明見《完全平方數的末兩位數字類型的另一種證明

#PerfectSquare = {00, e1, e4, 25, o6, e9}
def CheckPerfectSquare(num):
    #tens = 3, mean it is a odd number, tens = 4, mean it is a even number, otherwise, tens equal the value
    digitList = [   {'unit' : 0, 'tens' : 0}, 
                    {'unit' : 1, 'tens' : 4},  
                    {'unit' : 4, 'tens' : 4},  
                    {'unit' : 5, 'tens' : 2},  
                    {'unit' : 6, 'tens' : 3},  
                    {'unit' : 9, 'tens' : 4}];
    unit = num % 10;
    tens = (num % 100) / 10;
    
    for item in digitList:
        if item['unit'] == unit:
            if item['tens'] < 3:
                return item['tens'] == tens;
            else:
                #Check is odd or even number, check the first bit
                return item['tens'] & 1 == tens & 1;
    return  False;

def Fermat(num):
    x = int(math.sqrt(num));
    if x*x < num:
        x += 1;
    
    times = 0;
    x0 = x;
    #y^2 = x^2 - num
    while(True):
        y2 = x*x - num;
        if CheckPerfectSquare(y2):
            times += 1;
            y = int(math.sqrt(y2));
            if y*y == y2:
                break;
        x += 1;

    print "Loop : ", x - x0 +1, ", check perfect square :", times;
    print "x :", x, ", y :", y;
    return [x+y, x-y];

測試結果:

image

可以看出,用了完全平方數的性質后,將原來需要計算y的開方和比較y2的次數減少了13次(86%),我們知道計算乘法和開方式非常耗費時間的,減少這些次數后可以大大提高算法效率

 

4. 費馬因式分解最壞計算次數

x = (a+b)/2

∵ n = ab, b = n/a

∴ x = (a + n/a)/2

我們需求x的最大值,如果(a + n/a)是單調遞增或遞減的,我們很容易就得到x的最大值

設a >= b(b >=a 也一樣)

則 a2 >= ab = n

∴ a2 >= n   (a <= n)

設f(a) =  a + n/a

f(a+1) = (a+1) + n/(a+1)

f(a+1) – f(a) = (a+1) + n/(a+1) – (a + n/a)

                   = 1 + n/(a+1) –  n/a

                   = [(a+1)a + na –n(a+1)]/a

                   = (a2 –n + a)/[a(a+1)]

∵ a2 >= n

∴ (a2 –n + a) > 0

∴f(a+1) > f(a)

∴f(a)時單調遞增的

∵a <= n

∴當a = n時,f(a)最大,x也最大,x = (n + n/n)/2 = (n+1)/2

∴費馬因式分解最大次數 = x – sqrt(n) = (n+1)/2 – sqrt(n)

 

5. 費馬因式分解算法和素數判定

思考:當費馬因式分解算法為最壞次數時,n是什么數

當費馬因式分解算法為最壞次數時,可知a = n, b = 1, x = (n+1)/2, y = (n-1)/2

貌似其因子為本身和1,這和素數的性質非常像,看第1部分的1到9的費馬因式分解,貌似滿足這種條件的都是素數,那么大膽猜想一下:

假設:如果奇數n的費馬因式分解式 = n*1, 那么n為一個素數

反證:n不為素數, 則x在最大值之前就使x2 – n = y2

即需證明,當n不為素數,n = ab = (x+y)(x-y), x < (n+1)/2

那么 n = ab (n > a)

根據第4部分證明知 x = (a + n/a)/2 ,且f(a) =  a + n/a 是單調遞增的

∵a < n

∴f(a) < f(n) < n + n/n = n + 1

∴x < (n+1)/2

∴x不可能到最大次數,得證

 

增加部分code和測試如下:

if __name__ == '__main__':
    while(True) :
        num = int(raw_input("Input a odd num for fermat : "));
        if(1 == num & 1):
            break;
    
    retList = Fermat(num);
    print num, "=", retList[0], "*", retList[1];
    if num > 1 and 1 == retList[1]:
        print num, "is a prime number";

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM