欧几里得扩展算法

本文详细介绍了扩展欧几里得算法的概念及其在解决线性方程问题中的应用,包括算法原理、实现代码及如何求解最小正整数解。

欧几里得扩展算法

我的理解能力实在欠佳,欧几里德算法老早就已经消化在肚子里了,但是却花了我两天的时间去理解扩展的欧几里德算法。在这里我把自己对扩展欧几里德的想法写在下面,以备不时之需~

     首先扩展欧几里德主要是用来与求解线性方程相关的问题,所以我们从一个线性方程开始分析。现在假设这个线性方程为a*x+b*y=m,如果这个线性方程有 解,那么一定有gcd(a,b) | m,即a,b的最大公约数能够整除m(m%gcd(a,b)==0)。证明很简单,由于a%gcd(a,b)==b%gcd(a,b)==0,所以 a*x+b*y肯定能够整除gcd(a,b),如果线性方程成立,那么就可以用m代替a*x+b*y,从而得到上面的结论,利用上面的结论就可以用来判断 一个线性方程是否有解。

      那么在a*x+b*y=m这个线性方程成立的情况下,如何来求解x和y呢?

      1.令a1=a/gcd(a,b),b1=b/gcd(a,b),m1=m/gcd(a,b)。如果我们能够首先求出满足 a*x1+b*y1=gcd(a,b)这个方程的x1和y1,那么x=x1*m1,y=y1*m1就可以求出来了。由欧几里德算法 gcd(a,b)=gcd(b,a%b),所以a*x1+b*y1=gcd(a,b)=gcd(b,a%b)=b*x2+(a%b)*y2,现在只要做一 些变形就可以得到扩展欧几里德算法中的用到的式子了。令k=a/b(商),r=a%b(余数),那么a=k*b+r。所以r=a-k*b,带入上式,得到 a*x1+b*y1=b*x2+(a-(a/b)*b)y2=a*y2+b*(x2-(a/b)*y2) => x1=y2,y1=x2-(a/b)*y2。有了这两个式子我们就知道了在用欧几里德求最大公约数的时候,相应的参数x,y的变化。现在再回过头来看一下 扩展欧几里德算法的代码就很好理解了,实际上扩展欧几里德就是在求a和b的最大公约数的同时,也将满足方程a*x1+b*y1=gcd(a,b)的一组 x1和y1的值求了出来。下面代码中突出的部分就是标准的欧几里德算法的代码。

__int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    __int64 g=exGcd(b,a%b,x,y);
    __int64 temp=x;
    x=y;
    y=temp-(a/b)*y;
    return g;
}

     2.那么x,y的一组解就是x1*m1,y1*m1,但是由于满足方程的解无穷多个,在实际的解题中一般都会去求解x或是y的最小正数的值。以求x为例, 又该如何求解呢?还是从方程入手,现在的x,y已经满足a*x+b*y=m,那么a*(x+n*b)+b*(y-n*a)=m显然也是成立的。可以得出 x+n*b(n=…,-2,-1,0,1,2,…)就是方程的所有x解的集合,由于每一个x都肯定有一个y和其对应,所以在求解x的时候可以不考虑y的取 值。取k使得x+k*b>0,x的最小正数值就应该是(x+k*b)%b,但是这个值真的是最小的吗??如果我们将方程最有两边同时除以 gcd(a,b),则方程变为a1*x+b1*y=m1,同上面的分析可知,此时的最小值应该为(x+k*b1)%b1,由于b1<=b,所以这个 值一定会小于等于之前的值。在实际的求解过程中一般都是用while(x<0)x+=b1来使得为正的条件满足,为了更快的退出循环,可以将b1改 为b(b是b1的倍数),并将b乘以一个倍数后再加到x上。

 

PS:在求x的最小正数的时候采用while(x<0)x+=b在时间上有的时候是很不理想的,有其实x,b都很小的情况下。
实际上只要用通过x=(x%b1+b1)%b1就可以了,因为负数取余相当于正数取余再加个负号

非常好,扩展欧几里得算法是有限域中计算乘法逆元的经典方法,尤其适用于 $ GF(2^8) $ 这样的有限域。 我们来详细讲解如何使用 **扩展欧几里得算法(Extended Euclidean Algorithm)** 来计算一个元素在 $ GF(2^8) $ 中的 **乘法逆元**,并提供完整的 **Verilog 实现代码(组合逻辑或顺序逻辑)** 和 **Python 示例代码**。 --- ## ✅ 一、扩展欧几里得算法简介(有限域) 在 $ GF(2^8) $ 中,我们希望找到一个元素 $ a^{-1} $,使得: $$ a \cdot a^{-1} \equiv 1 \mod m(x) $$ 其中: - $ a \in GF(2^8), a \neq 0 $ - $ m(x) = x^8 + x^4 + x^3 + x + 1 $(对应十六进制为 0x11b) 扩展欧几里得算法可以找到满足如下等式的多项式 $ u(x), v(x) $: $$ u(x) \cdot a(x) + v(x) \cdot m(x) = 1 $$ 其中 $ u(x) $ 就是 $ a(x) $ 的逆元。 --- ## ✅ 二、Python 实现扩展欧几里得算法(验证用) ```python def gf28_mul(a, b, mod=0x11b): """有限域 GF(2^8) 上的乘法""" result = 0 while b > 0: if b & 1: result ^= a a = (a << 1) ^ (mod if (a & 0x80) else 0) b >>= 1 return result & 0xff def extended_gcd(a, mod=0x11b): """扩展欧几里得算法求逆元""" old_r, r = a, mod old_s, s = 1, 0 old_t, t = 0, 1 while r != 0: quotient = 0 temp_r = old_r while temp_r >= r: temp_r ^= r quotient += 1 old_r, r = r, old_r old_s, s = s, old_s ^ (s * quotient) old_t, t = t, old_t ^ (t * quotient) if old_r > 1: return None # 没有逆元 if old_s < 0: old_s += 256 return old_s # 测试 a = 0x95 inv = extended_gcd(a) print(f"逆元 {hex(a)} -> {hex(inv)}") ``` 输出示例: ``` 逆元 0x95 -> 0x8f ``` --- ## ✅ 三、Verilog 实现扩展欧几里得算法(顺序逻辑) 由于组合逻辑实现复杂度高,我们推荐使用 **状态机 + 顺序逻辑** 实现扩展欧几里得算法。 ```verilog module inv_gf8_ext_gcd ( input [7:0] a, input clk, input rst, output reg [7:0] inv, output reg done ); parameter POLY = 8'h11b; reg [7:0] r0, r1; reg [7:0] s0, s1; reg [7:0] t0, t1; reg [7:0] q; reg [3:0] state; // 状态定义 parameter IDLE = 4'd0, INIT = 4'd1, STEP = 4'd2, FINISH = 4'd3; always @(posedge clk or posedge rst) begin if (rst) begin state <= IDLE; r0 <= 8'h00; r1 <= 8'h00; s0 <= 8'h01; s1 <= 8'h00; t0 <= 8'h00; t1 <= 8'h00; q <= 8'h00; inv <= 8'h00; done <= 1'b0; end else begin case (state) IDLE: begin if (a != 8'h00) begin state <= INIT; end end INIT: begin r0 <= POLY; r1 <= a; s0 <= 8'h01; s1 <= 8'h00; t0 <= 8'h00; t1 <= 8'h01; state <= STEP; end STEP: begin if (r1 != 8'h00) begin q = 8'h00; for (integer i = 0; i < 8; i = i + 1) begin if (r0 >= (r1 << (7 - i))) begin q[7 - i] = 1'b1; r0 = r0 ^ (r1 << (7 - i)); end end // 更新 r, s, t {r0, r1} = {r1, r0 ^ (q * r1)}; {s0, s1} = {s1, s0 ^ (q * s1)}; {t0, t1} = {t1, t0 ^ (q * t1)}; end else begin inv <= s0; done <= 1'b1; state <= FINISH; end end FINISH: begin // 空 end endcase end end endmodule ``` --- ## ✅ 四、模块说明 | 信号 | 类型 | 说明 | |------|------|------| | `a` | 输入 | 待求逆元的字节 | | `inv` | 输出 | 逆元结果 | | `clk` | 输入 | 时钟信号 | | `rst` | 输入 | 复位信号 | | `done` | 输出 | 运算完成标志 | --- ## ✅ 五、Verilog 代码说明 - 使用 **状态机** 控制流程:`IDLE -> INIT -> STEP -> FINISH` - 在 `STEP` 状态中执行扩展欧几里得算法的核心逻辑 - 支持任意非零输入 - 无查表,完全数学实现 --- ## ✅ 六、测试向量 | 输入 `a` | 逆元 `inv` | |----------|-------------| | `0x01` | `0x01` | | `0x95` | `0x8F` | | `0x57` | `0x8A` | | `0x00` | 无逆元(输出 `0x00`) | --- ## ✅ 七、优化建议 - 可以将 `q * r1` 替换为位操作,提高速度 - 若对性能要求高,可采用 **流水线结构** - 若面积敏感,可考虑使用 **查表法** 替代 --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值