2013-08-07 35 views
7

Tôi đang cố gắng tìm một cách hiệu quả để tính toán Euler's totient function.Máy tính Eulers Chức năng hoàn hảo

Điều gì sai với mã này? Nó dường như không hoạt động.

def isPrime(a): 
    return not (a < 2 or any(a % i == 0 for i in range(2, int(a ** 0.5) + 1))) 

def phi(n): 
    y = 1 
    for i in range(2,n+1): 
     if isPrime(i) is True and n % i == 0 is True: 
      y = y * (1 - 1/i) 
     else: 
      continue 
    return int(y) 
+6

'1/i' không làm những gì bạn nghĩ - hãy thử. – orlp

+2

sử dụng python3 thay vì python2 :-) – 6502

+3

Hoặc đặt 'từ __future__ bộ phận nhập' ở đầu mã của bạn để cho phép phân chia phao bằng Python 2. –

Trả lời

20

Đây là một cách nhanh hơn nhiều, làm việc, dựa trên mô tả này trên Wikipedia:

Vì vậy, nếu n là một số nguyên dương, sau đó φ (n) là số các số nguyên k trong phạm vi 1 ≤ k ≤ n mà gcd (n, k) = 1.

Tôi không nói đây là nhanh nhất hoặc sạch nhất, nhưng nó hoạt động.

import fractions 

def phi(n): 
    amount = 0   
    for k in range(1, n + 1): 
     if fractions.gcd(n, k) == 1: 
      amount += 1 
    return amount 
+0

Ý của bạn là dải ô (1, n + 1)? – douggard

+0

@douggard Có, cảm ơn bạn. – orlp

+0

Những thuộc tính này có ích Nếu p là số nguyên tố, ϕ (p) = p − 1 là gcd (p, q) = 1 nơi 1 <= q

0, ϕ (p^k) = p^k − p^(k − 1) Nếu a và b tương đối nguyên tố, ϕ (ab) = ϕ (a) .ϕ (b) http: // e-maxx-eng. github.io/algebra/phi-function.html –

2

Dường như bạn đang cố gắng sử dụng công thức sản phẩm của Euler, nhưng bạn không tính số lượng số nguyên tố chia. Bạn đang tính số nguyên tố tương đối chính cho a.

Bên cạnh đó, kể từ ngày 1 và tôi đều số nguyên, do đó là bộ phận, trong trường hợp này bạn luôn có được 0.

4

Bạn có ba vấn đề khác nhau ...

  1. y cần phải được bằng n giá trị như ban đầu, không 1
  2. theo một số người đã đề cập trong các ý kiến, không sử dụng phân chia số nguyên
  3. n % i == 0 is True không làm những gì bạn nghĩ vì Python chuỗi các so sánh! Ngay cả khi n % i bằng 0 thì 0 == 0TrueNHƯNG0 is TrueFalse! Sử dụng parens hoặc chỉ cần thoát khỏi so sánh với True vì đó là không cần thiết anyway.

Sửa những vấn đề,

def phi(n): 
    y = n 
    for i in range(2,n+1): 
     if isPrime(i) and n % i == 0: 
      y *= 1 - 1.0/i 
    return int(y) 
2

Liên quan đến hiệu quả, tôi đã không nhận thấy bất cứ ai đề cập đến rằng gcd (k, n) = UCLN (n-k, n). Sử dụng thực tế này có thể tiết kiệm gần một nửa công việc cần thiết cho các phương pháp liên quan đến việc sử dụng gcd. Chỉ cần bắt đầu đếm với 2 (vì 1/n và (n-1)/k sẽ luôn không thể hủy được) và thêm 2 mỗi lần gcd là một.

+0

Bạn không xem xét công việc cần thiết để tính toán công việc cần thiết để so sánh 'n' với' 2 * k', cũng như công việc cần thiết để trừ 'nk'. – msinghal

3

Tôi đang làm việc trên thư viện mật mã trong python và đây là những gì tôi đang sử dụng. gcd() là phương pháp của Euclid để tính ước số chung lớn nhất và phi() là hàm tổng.

def gcd(a, b): 
    while b: 
     a, b=b, a%b 
    return a 
def phi(a): 
    b=a-1 
    c=0 
    while b: 
     if not gcd(a,b)-1: 
      c+=1 
     b-=1 
    return c 
1

Trên thực tế để tính toán phi (bất kỳ số nói n)
Chúng tôi sử dụng Formula
trong đó p là thừa số nguyên tố của n.

Vì vậy, bạn có vài sai lầm trong mã của bạn:
1. y nên bằng n
2.Đối với 1/i thực sự là 1i cả hai đều là số nguyên để đánh giá của chúng cũng sẽ là số nguyên, do đó sẽ dẫn đến kết quả sai.

Đây là mã có các chỉnh sửa được yêu cầu.

 
def phi(n): 
    y = n 
    for i in range(2,n+1): 
     if isPrime(i) and n % i == 0 : 
      y -= y/i 
     else: 
      continue 
    return int(y) 
Các vấn đề liên quan