2010-11-01 50 views
5

Tôi cần một cách để tính toán:Lũy thừa Modular trong Java

(g^u * y^v) mod p 

trong Java.

tôi đã tìm thấy thuật toán này để tính (g^u) mod p:

int modulo(int a,int b,int c) { 
    long x=1 
    long y=a; 
    while(b > 0){ 
     if(b%2 == 1){ 
      x=(x*y)%c; 
     } 
     y = (y*y)%c; // squaring the base 
     b /= 2; 
    } 
    return (int) x%c; 
} 

và nó hoạt động tuyệt vời, nhưng tôi dường như không thể tìm thấy một cách để làm điều này cho

(g^u * y^v) mod p 

vì kỹ năng toán học của tôi kém chất lượng.

Để đặt nó trong ngữ cảnh, đó là cho một thực hiện java của một DSA "giảm" - phần xác minh yêu cầu điều này phải được giải quyết.

+0

Tôi giả sử p là số nguyên tố, phải không? –

+0

vâng, p là số nguyên tố, tôi nghĩ điều này giải quyết nó: (g^u * y^v) mod p = (g^u mod p) * (y^v mod p) mod p, mặc dù tôi chỉ thử nghiệm nó với số nhỏ cho đến nay –

+0

Và nó có lớn không? Phần 'mod p' trông giống như bạn muốn dùng' BigInteger' thay vì dài. –

Trả lời

8

Giả sử rằng hai yếu tố này sẽ không tràn, tôi tin bạn có thể đơn giản hóa một biểu thức như vậy theo cách này:

(x * y) mod p = ((x mod p)*(y mod p)) mod p. Tôi chắc rằng bạn có thể tìm ra từ đó.

+0

vâng, tôi nghĩ rằng đây là cách, cho đến nay tôi đã thực hiện các bài kiểm tra về số lượng nhỏ với điều này, và nó có vẻ là làm việc –

+1

Tôi đoán rằng nó có thể không OK giả định rằng các yếu tố sẽ không tràn, nhưng tôi không thể chắc chắn. –

+0

Các yếu tố sẽ không tràn miễn là (p-1) * (p-1) vừa với một 'int'. Nếu không, chúng ta sẽ phải sử dụng 'long' cho x và y. Thực tế – MAK

1

Hãy thử

(Math.pow (q, u) * Math.pow (y, v))% p

+0

Tôi đoán lý do mà anh ta yêu cầu là các con số quá lớn cho cách tiếp cận đơn giản để làm việc ... –

+0

Nếu đúng như vậy, tại sao không sử dụng BigInteger? – Nicholas

+0

Math.pow() nhận và trả về gấp đôi. http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Math.html # pow% 28double,% 20double% 29 – wnoise

4

Đoạn mã đó thực hiện thuật toán "lũy thừa nhanh" nổi tiếng, còn được gọi là Exponentiation by squaring.

Nó cũng sử dụng thực tế là (a * b) mod p = ((a mod p) * (b mod p)) mod p. (Cả hai bổ sung và phép nhân được bảo tồn cấu trúc dưới một mô đun chính - đó là một homomorphism). Bằng cách này, tại mọi điểm trong thuật toán, nó giảm xuống các số nhỏ hơn p.

Trong khi bạn có thể thử tính toán những điều này theo kiểu xen kẽ trong một vòng lặp, thì không có lợi ích thực sự để làm như vậy. Chỉ cần tính chúng một cách riêng biệt, nhân chúng lại với nhau và lấy mod lần cuối.

Được cảnh báo rằng bạn sẽ bị tràn nếu p^2 lớn hơn int thể hiện lớn nhất và điều này sẽ khiến bạn có câu trả lời sai. Đối với Java, việc chuyển sang số nguyên lớn có thể thận trọng, hoặc ít nhất là kiểm tra thời gian chạy trên kích thước của p và ném một ngoại lệ.

Cuối cùng, nếu điều này là dành cho mục đích mã hóa, có thể bạn đang sử dụng thư viện để thực hiện việc này, thay vì tự thực hiện nó. Nó rất dễ dàng để làm một cái gì đó hơi sai mà dường như làm việc, nhưng cung cấp tối thiểu để không có bảo mật.

+0

Nó thực sự là cho các mục đích mã hóa, nhưng nó là cho một bài tập ở trường, nơi chúng tôi đang thực hiện DSA mình. Cảm ơn bạn đã trả lời sâu sắc của bạn! –