Python NZMATH 模块的数论计算探索之一

前言

在上一篇文章中,笔者给出了 NZMATH 模块的介绍和安装,以及进行 ECPP 大整数的素性判定。本文我们将继续探索 NZMATH 的数论计算功能。


一、Arith1 方法 —— 算术函数杂项汇总

1.1 开根取整

对自然数 N N N 的根号取下整:

from nzmath import *

arith1.floorsqrt(22)

以上输出结为 4 4 4 。事实上, 22 ≈ 4.6904 \sqrt{22} \approx 4.6904 22 4.6904 ,取下整即朝着 0 0 0 的方向取整,结果的确为 4 4 4 。注意,此方法只能针对正整数进行运算。

对自然数 N N N 开高次根号并取下整:

arith1.floorpowerroot(1000, 4)

上述代码输出结果 5 5 5 ,系对 1000 1000 1000 4 4 4 次根号并取下整。

1.2 Legendre (Jacobi) 符号

Legendre 符号对于数论爱好者都并不陌生,即下述定义( p p p 为奇素数) ( a p ) = { 1 , p ∤ a    且存在整数    x    使得    x 2 ≡ a m o d    p − 1 , 不存在整数    x    使得    x 2 ≡ a m o d    p 0 p ∣ a \left( \frac{a}{p} \right) = \left\{ \begin{aligned} 1&, \quad &&p \nmid a \; 且 存在整数\; x \; 使得 \; x^2 \equiv a \mod p \\ -1&, \quad &&不存在整数\; x\; 使得 \; x^2 \equiv a \mod p \\ 0& \quad &&p\mid a \\ \end{aligned} \right. (pa)= 110,,pa且存在整数x使得x2amodp不存在整数x使得x2amodppa 下面求解勒让德符号 ( 399541 999907 ) \left( \frac{399541}{999907} \right) (999907399541) ,其中分子分母皆为素数。

arith1.legendre(399541,999907) 

输出结果为 1 1 1 ,即 399541 399541 399541 是模 999907 999907 999907 的二次剩余。这表明二次同余方程 x 2 ≡ 399541 m o d    999907 x^2 \equiv 399541 \mod 999907 x2399541mod999907 有解。那么这个解的一个特殊情形又是什么呢 ?我们使用下述语句来求 x x x

arith1.modsqrt(399541, 999907)

输出结果为 108094 108094 108094 ,可以验证, x ≡ 108094 m o d    999907 x \equiv 108094 \mod 999907 x108094mod999907 x 2 ≡ 399541 m o d    999907 x^2 \equiv 399541 \mod 999907 x2399541mod999907 的解。它还有另一个伴随解 x ≡ − 108094 ≡ 891813 m o d    999907 x \equiv -108094 \equiv 891813 \mod 999907 x108094891813mod999907 ,如果不计此伴随解,则二次同余式 x 2 ≡ 399541 m o d    999907 x^2 \equiv 399541 \mod 999907 x2399541mod999907 仅有唯一的一组解。

下面继续求解勒让德符号 ( 343917 999907 ) \left( \frac{343917}{999907} \right) (999907343917) ,其中的分子为合数。

arith1.legendre(343917,999907)

输出结果为 1 1 1 ,表明二次同余方程 x 2 ≡ 343917 m o d    999907 x^2 \equiv 343917\mod 999907 x2343917mod999907 有解。

arith1.modsqrt(343917, 999907) 

通过上述代码求其解为 x ≡ 468521 m o d    999907 x \equiv 468521 \mod 999907 x468521mod999907 ,该解也是唯一的。

Jacobi 符号是勒让德符号的推广,由勒让德符号定义如下: ( a n ) = ( a p 1 ) α 1 ( a p 2 ) α 2 ⋯ ( a p k ) α k \left( \frac{a}{n} \right) = \left( \frac{a}{p_1} \right)^{\alpha_1}\left( \frac{a}{p_2} \right)^{\alpha_2} \cdots \left( \frac{a}{p_k} \right)^{\alpha_k} (na)=(p1a)α1(p2a)α2(pka)αk 其中 n = p 1 α 1 p 2 α 2 ⋯ p k α k n = p_1^{\alpha_1}p_2^{\alpha_2} \cdots p_k^{\alpha_k} n=p1α1p2α2pkαk 为大于 1 1 1 的奇数。

现在我们求解雅可比符号 ( 844143 985067 ) \left( \frac{844143}{985067} \right) (985067844143) ,其中分子分母皆为合数:

arith1.legendre(844143,985067)

输出结果为 1 1 1 ,对于雅可比符号,此时还不足以说明二次同余方程 x 2 ≡ 844143 m o d    985067 x^2 \equiv 844143\mod 985067 x2844143mod985067 有解。我们考虑下面的运算:

arith1.modsqrt(844143, 985067)

上述代码输出结果为 639990 639990 639990 ,但实际上, 639990 639990 639990 并不是二次同余方程 x 2 ≡ 844143 m o d    985067 x^2 \equiv 844143\mod 985067 x2844143mod985067 的解。出现这个问题的原因是,arith1.modsqrt(a, p) 中的第二个参数 p p p 必须是素数,否则会出现如上错误的结果。 那么该同余方程是否有解 ?我们通过下述代码进行搜索:

rst = []
for i in range(1,985068):
    if (i**2 - 844143) % 985067 == 0:
        rst.append(i)
        
rst

结果输出的是一个空列表,说明二次同余方程 x 2 ≡ 844143 m o d    985067 x^2 \equiv 844143\mod 985067 x2844143mod985067 无解。因此雅可比符号为 1 1 1 ,也不能说明二次同余方程有解但雅可比符号为 − 1 -1 1 ,则一定有二次同余方程无解。例如:

arith1.legendre(308081,688781)

上述雅可比符号 ( 308081 688781 ) \left( \frac{308081}{688781} \right) (688781308081) 的计算结果为 − 1 -1 1 ,表明 x 2 ≡ 308081 m o d    688781 x^2 \equiv 308081\mod 688781 x2308081mod688781 无解。

最后举一个雅可比符号为 1 1 1 ,且有解的例子 ( 308071 688781 ) \left( \frac{308071}{688781} \right) (688781308071) ,(其中分子分母皆为合数):

arith1.legendre(308071,688781)

计算输出雅可比符号的值为 1 1 1 ,而且此时二次同余方程 x 2 ≡ 308071 m o d    688781 x^2 \equiv 308071\mod 688781 x2308071mod688781 有多组解 x ≡ 16977 , 162705 , 526076 , 671804 m o d    688781 x \equiv 16977, 162705, 526076, 671804 \mod 688781 x16977,162705,526076,671804mod688781 即便去掉伴随解,此时仍有不唯一的两组解 x ≡ 16977 , 162705 m o d    688781 (1) x \equiv 16977, 162705 \mod 688781 \tag{1} x16977,162705mod688781(1) 值得注意的是 n = 23 ⋅ 29947 n=23\cdot 29947 n=2329947 ,则有 ( 308071 688781 ) = ( 308071 23 ) ( 308071 29947 ) \left( \frac{308071}{688781} \right) = \left( \frac{308071}{23} \right) \left( \frac{308071}{29947} \right) (688781308071)=(23308071)(29947308071) 由程序计算知, ( 308071 23 ) = ( 308071 29947 ) = 1 \left( \frac{308071}{23} \right) = \left( \frac{308071}{29947} \right) =1 (23308071)=(29947308071)=1 因此二次同余方程 x 2 ≡ 308071 m o d    29947 x^2 \equiv 308071\mod 29947 x2308071mod29947 有唯一解 x ≡ 16977 m o d    29947 (2) x \equiv 16977 \mod 29947 \tag{2} x16977mod29947(2) 事实上,满足 ( 1 ) (1) (1) 式中 x ≡ 16977 m o d    688781 x \equiv 16977 \mod 688781 x16977mod688781 x x x,也一定满足 ( 2 ) (2) (2) 式。故同余方程 x 2 ≡ 308071 m o d    688781 x^2 \equiv 308071\mod 688781 x2308071mod688781 x 2 ≡ 308071 m o d    29947 x^2 \equiv 308071\mod 29947 x2308071mod29947 各自都有一部分解是相同的,但两者解集不完全相同。

以下我们验证雅可比符号的二次互反律,其中要求 ( a n ) \left( \frac{a}{n} \right) (na) a a a n n n 为大于 1 1 1 的奇数:

a = 308071
n = 688781
A = arith1.legendre(a,n)
B = (-1)**((a-1)*(n-1)//4)*arith1.legendre(n,a)
A == B

输出结果为 True ,这样就验证了二次互反律。

1.3 模 q q q 的乘积逆元

对于整数 n n n q q q , ( n , q ) = 1 (n, q)=1 (n,q)=1 ,若有 m m m 使得 n ⋅ m ≡ 1 m o d    q n\cdot m \equiv 1 \mod{q} nm1modq ,则称 m m m 为模 q q q n n n 的逆元。我们可以很容易地进行求解,比如 111111 ⋅ m ≡ 1 m o d    993341 111111\cdot m \equiv 1 \mod{993341} 111111m1mod993341 ,来求解逆元 m m m

arith1.inverse(111111, 993341)

输出结果为 m = 408347 m = 408347 m=408347

1.4 中国剩余定理的求解

中国剩余定理为求解如下的一次同余方程组: { x ≡ a 1 m o d    m 1 x ≡ a 2 m o d    m 2 ⋯ x ≡ a n m o d    m n \left\{ \begin{aligned} &x \equiv a_1 \mod{m_1} \\ &x \equiv a_2 \mod{m_2} \\ & \cdots \\ & x \equiv a_n \mod{m_n} \end{aligned} \right. xa1modm1xa2modm2xanmodmn 其中要求 m 1 , m 2 , . . . , m n m_1, m_2, ..., m_n m1,m2,...,mn 两两互素。例如求解如下的方程组: { x ≡ 2 m o d    250777 x ≡ 3 m o d    555677 x ≡ 5 m o d    794111 \left\{ \begin{aligned} &x \equiv 2 \mod{250777} \\ &x \equiv 3 \mod{555677} \\ & x \equiv 5 \mod{794111} \end{aligned} \right. x2mod250777x3mod555677x5mod794111 该方程组的求解代码为:

# 列表中的第一个元素是余数,第二个是模数
arith1.CRT([[2, 250777], [3, 555677], [5, 794111]])

输出的结果为 79143032176845751 79143032176845751 79143032176845751 ,而实际的结果为 x ≡ 79143032176845751 m o d    110660170719250219 x \equiv 79143032176845751 \mod{110660170719250219} x79143032176845751mod110660170719250219 其中模数为 110660170719250219 = m 1 ⋅ m 2 ⋅ m 3 110660170719250219=m_1 \cdot m_2 \cdot m_3 110660170719250219=m1m2m3

1.5 判断平方数

print(arith1.issquare(1234321))
print(arith1.issquare(7654321))

输出结果 1111 1111 1111 0 0 0 ,前者表明 1234321 = 111 1 2 1234321 = 1111^2 1234321=11112 ,后者表明 7654321 7654321 7654321 不是一个平方数。

二、Arygcd 方法 —— 三类最大公约数的计算

2.1 整数的最大公因子

arygcd.binarygcd(113,1017)

输出结果为 113 113 113

2.2 高斯整数的最大公因子

我们也可以求两个高斯整数的最大公因子:

arygcd.arygcd_i(1,13,13,11)

输出结果为 ( 1 , 1 ) (1,1) (1,1) ,即高斯整数 1 + 13 i 1+13i 1+13i 13 + 11 i 13+11i 13+11i 的最大公因子为 1 + i 1+i 1+i

2.3 艾森斯坦整数的最大公因子

进一步,开可以计算两个艾森斯坦整数的最大公因子。艾森斯坦整数的定义如下: z = a + b ω , ω = e 2 π i 3 z =a + b\omega , \quad \omega=e^{\frac{2\pi i}{3}} z=a+,ω=e32πi 以下给出计算代码:

arygcd.arygcd_w(2, 13, 33, 15)

输出结果为 ( 4 , 5 ) (4,5) (4,5) ,即 2 + 13 ω 2+13\omega 2+13ω 33 + 15 ω 33+15\omega 33+15ω 的最大公因子为 4 + 5 ω 4+5\omega 4+5ω

至此,我们已经初步体会了 NAMATH 在数论上的编程实践,也欢迎读者浏览本文的后续内容。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tengfei Wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值