1. 程式人生 > 其它 >js 基本語法

js 基本語法

  • 擴充套件歐幾里得演算法

  擴充套件歐幾里得演算法(英語:Extended Euclidean algorithm)是歐幾里得演算法(又叫輾轉相除法)的擴充套件。已知整數a、b,擴充套件歐幾里得演算法可以在求得a、b的最大公約數的同時,能找到整數x、y(其中一個很可能是負數),使它們滿足貝祖等式:

  ax + by = gcd(a, b)

如果a是負數,可以把問題轉化成:

  |a|(-x) + by = gcd(|a|, x) (|a|為a的絕對值,然後令x' = (-x)。

通常談到最大公約數時,我們都會提到一個非常基本的事實(貝祖等式給定):給定二個整數a、b,必存在整數x、y使得ax + by = gcd(a,b)

  眾所周知,已知兩個數a和b,對它們進行輾轉相除,可得它們的最大公約數。不過,在歐幾里得演算法中,我們僅僅利用了每步帶餘除法所得的餘數。擴充套件歐幾里得演算法還利用了帶餘除法所得的商,在輾轉相除的同時也能得到貝祖等式中的x、y兩個係數。以擴充套件歐幾里得演算法求得的係數是滿足裴蜀等式的最簡係數。

另外,擴充套件歐幾里得演算法是一種自驗證演算法,最後一步得到的si+1和ti+1(si+1和ti+1的含義如下)乘以gcd(a,b)之後恰好是a和b,可以用來驗證計算結果是否正確。

擴充套件歐幾里得演算法可以用來計算模反元素(也叫模逆元),求出模反元素是RSA加密演算法中獲得所需公鑰、私鑰的必要步驟。

  • 演算法和舉例

在標準的歐幾里得演算法中,我們記欲求最大公約數的兩個數為a和b,第i步帶餘除法得到的商為qi,餘數為ri+1,則歐幾里得演算法可以寫成如下形式:

     r0 = a

     r1= b

     .......

    ri+1 = ri-1 - qiri 且 0 ≤ ri+1 < |ri|

      ......

當某步得到的 ri+1= 0 時,計算結束。上一步得到的ri即為a,b的最大公約數。

擴充套件歐幾里得演算法在qi,ri的基礎上增加了兩組序列,記作si和ti,並s0 = 1, s1 = 0, t0 = 0, t1 = 1,在歐幾里得演算法每步計算ri+1= ri-1

- qiri之外額外計算

si+1 = si-1 - qisi和 ti+1 = ti-1 - qiti,亦即:

    r0= a      r1= b

     s0 = 1      s1 = 0

     t0= 0      t1 = 1

     ...... ......

   ri+1= ri-1- qiri 且 0 ≤ ri+1< |ri|  

   si+1= si-1- qi si

   ti+1= ti-1- qi ti

    ......

演算法結束條件與歐幾里得演算法一致,也是ri+1= 0,此時所得的si和ti即滿足等式gcd(a, b) = ri = asi + bti

下表以a = 240,b = 46為例演示了擴充套件歐幾里得演算法:

序號i qi−1 餘數ri si ti
0 240 1 0
1 46 0 1
2 240÷46=5 240−5×46=10 1−5×0=1 0 −5× 1 = −5
3 46÷10=4 46−4×10=6 0−4×1=−4 1 −4× −5 = 21
4 10÷6=1 10−1×6=4 1−1×−4=5 −5 −1× 21 = −26
5 6÷4=1 6−1×4=2 −4−1×5=−9 21 −1× −26 =47
6 4÷2=2 4−2×2=0 5−2×−9=23 −26 −2× 47 =−120

所得的最大公因數是2,所得貝祖等式為gcd(240, 46) = 2 = -9* 240 + 47 * 46。同時還有自驗證等式|23| * 2 = 46 和 |-120| * 2 = 240。

  • 擴充套件歐幾里得演算法和模逆元實現

  以下是擴充套件歐幾里德演算法的Rust實現:

 1 pub fn extend_euclidean(a: isize,b: isize)->(isize,isize,isize){
 2     if b == 0{
 3         return ( 1,0,a);
 4     }else {
 5         let (mut old_r,mut r) = (a,b);
 6         let (mut old_s,mut s) = (1,0);
 7         let (mut old_t,mut t) = (0,1);
 8         while r != 0{
 9             let q = old_r/r;
10 
11             let temp = old_r;
12             old_r = r;
13             r = temp - q*r;
14 
15             let temp = old_s;
16             old_s = s;
17             s = temp - q*s;
18 
19             let temp = old_t;
20             old_t = t;
21             t = temp - q*t;
22         }
23         (old_s,old_t,old_r)
24     }
26 }

模逆元Rust實現:

 1 pub fn mod_inverse(a: isize,n:isize)->Option<isize>{
 2     let (s,_t,gcd) = extend_euclidean(a,n);
 3     if gcd != 1{
 4        return None;
 5     }
 6     if s > 0{
 7         Some(s)
 8     }else {
 9         Some(s+n)
10     }
11 }

擴充套件歐幾里得演算法以及模逆元測試程式碼:

 1     #[test]
 2     fn ext_gcd_test(){
 3         let a = 7;
 4         let n = 977;
 5         let (s,t,gcd) = extend_euclidean(a,n);
 6         assert_eq!((-279,2,1),extend_euclidean(7,977));
 7 
 8         assert_eq!(mod_inverse(47,977),Some(686));
 9 
10     }