歐拉函數(Euler' totient function )

歐拉函數(Euler' totient function )

  • Author: Jasper Yanghtml

  • School: Buptpython

前言

gamma函數的求導會出現所謂的歐拉函數(phi),在一篇論文中我須要對好幾個歐拉函數求值,結果不能理解,當即去google,發現了一個開源的python庫能夠用來計算歐拉函數app

class eulerlib.numtheory.Divisors(maxnum=1000)
    Implements methods related to prime factors and divisors.

    Parameters:    maxnum – Upper limit for the list of primes. (default = 1000)
    divisors(num)
        Returns a list of ALL divisors of num (including 1 and num).
        
        Parameters:    num – An integer for which divisors are needed.
        Returns:    A list [d1,d2,...dn] of divisors of num
    
    phi(num)
        Returns the number of totatives of num

        Parameters:    num – Integer for which number of totatives are needed.
        Returns:    Number of totatives of num

Note A totative of an integer num is any integer i such that, 0 < i < n and GCD(i,num) == 1.
Uses Euler’s totient function.
函數

這個函數到這裏並不能看懂用法和意義,下面我經過介紹兩個概念來讓你們慢慢理解這個過程。google

Totative(不知道怎麼翻譯)

from wiki

在數論中,一個給定的n的totative是一個符合大於0而且小於等於n的k,而且這個k和n是互質數(什麼是互質數呢)。翻譯

互質數爲數學中的一種概念,即兩個或多個整數的公因數只有1的非零天然數。公因數只有1的兩個非零天然數,叫作互質數。

歐拉方程 $$ \phi(x) $$ 就是在計算n的totative個數。
在n的乘法模下的totatives造成了模n乘法羣( Multiplicative group of integers modulo n )。 --->後面這句涉及的羣的知識我去維基上了解下後沒看懂,放棄了,將來有機會看看中文資料理解一下再添加進來吧。 wiki傳送門code

Euler's totient function

這個就是主角歐拉函數。htm

from wiki

在數論中,對正整數n,歐拉函數 $$ \varphi (n) $$ 是小於或等於n的正整數中與n互質的數的數目。此函數以其首名研究者歐拉命名,它又稱爲φ函數(由高斯所命名)或是歐拉總計函數[1](totient function,由西爾維斯特所命名)。
例如 $$ \varphi (8)=4 $$,由於1,3,5,7均和8互質。
歐拉函數其實是模n的同餘類所構成的乘法羣(即環 $$ {\mathbb {Z}}/n{\mathbb {Z}} $$ 的全部單位元組成的乘法羣)的階。這個性質與拉格朗日定理一塊兒構成了歐拉定理的證實。ip

若n是質數p的k次冪, $$ \varphi (n)=\varphi (p^{k})=p^{k}-p^{{k-1}}=(p-1)p^{{k-1}} $$ ,由於除了p的倍數外,其餘數都跟n互質。get

若 $$ n=p_{1}^{k_{1}}p_{2}^{k_{2}}\cdots p_{r}^{k_{r}} $$

則 $$ \varphi (n)=\prod _{{i=1}}^{r}p_{i}^{{k_{i}-1}}(p_{i}-1)=\prod _{{p\mid n}}p^{{\alpha _{p}-1}}(p-1)=n\prod _{{p|n}}\left(1-{\frac {1}{p}}\right) $$
其中 $$ \alpha _{p} $$ 是使得 $$ p^{{\alpha }} $$ 整除n的最大整數 $ alpha $(這裏 $$ \alpha _{p_{i}}=k_{i} $$ )。

例如 $$ \varphi (72)=\varphi (2^{3}\times 3^{2})=2^{{3-1}}(2-1)\times 3^{{2-1}}(3-1)=2^{2}\times 1\times 3\times 2=24 $$

個人理解

爲何會有兩個法則,一個是基本的計算而另外一個是連乘,其實就是由於認爲全部的數均可以拆解成兩個素數的k次冪的形式。

我須要的知識以上就足夠了,若是須要更多的理解,看下面的連接

Eulerlib

這是個開源的python語言的實現庫
咱們主要使用裏面的

eulerlib.numtheory.Divisors(maxnum=1000)下的

phi函數
使用過程,
e = eulerlib.numtheory.Divisors(10000) # 這裏的10000是最大值,默認是1000
e.phi(100) # 求phi(100)

使用十分簡單。

這個函數的實現源碼以下: 源碼傳送門

def phi(self,num):
        """Returns the number of `totatives 
        <http://en.wikipedia.org/wiki/Totative>`_ of *num*
        
        :param num: Integer for which number of totatives are needed.
        :returns: Number of totatives of *num*
        
        .. note::
        
            A totative of an integer *num* is any integer *i* such that,
            0 < i < n and *GCD(i,num) == 1*.
        
        Uses `Euler's totient function 
        <http://en.wikipedia.org/wiki/Euler%27s_totient_function>`_.
        """
        if(num < 1):
            return 0
        if(num == 1):
            return 1
        if(num in self.primes_table):    # 這個素數的table一開始就有了,從別的包導來的,去看定義就是maxnum之內的全部素數
            return num-1
        pfs = self.prime_factors_only(num) # 這個步驟就是找出p了
        prod = num
        for pfi in pfs:
            prod = prod*(pfi-1)/pfi
        return prod



    
    def prime_factors_only(self,num):
        """Returns the `prime factors 
        <http://en.wikipedia.org/wiki/Prime_factor>`_ *pf* :sub:`i` of *num*.
        
        :param num: An integer for which prime factors are needed
        :returns: A list [pf1,pf2,...pfi] of prime factors of *num*
        """
        if num in self.pfactonly_table:
            return self.pfactonly_table[num]
        elif ((num < 2) or (num > self.limit)):
            return []
        elif num in self.primes_table:
            self.pfactonly_table[num] = [num]
            return [num]
        else:
            result = []
            tnum = num
            for prime in self.primes_table:
                if(tnum%prime==0):
                    result.append(prime)
                    pdiv = prime*prime
                    while(tnum%pdiv == 0):
                        pdiv *= prime
                    pdiv //= prime        # 這個//= 和 /=彷佛沒有區別
                    tnum //= pdiv
                    if(tnum in self.primes_table):
                        result.append(tnum)
                        break
                    elif(tnum == 1):
                        break
            self.pfactonly_table[num] = result
            return result

源碼看起來也十分的簡潔易懂,就是爲了找出p1和p2而後就能夠分別求phi值再相乘了。

paper done : 2017/4/19
相關文章
相關標籤/搜索