📌  相关文章
📜  Java番石榴 |带示例的 LongMath 类的 mod(long x, long m)(1)

📅  最后修改于: 2023-12-03 15:32:04.358000             🧑  作者: Mango

Java番石榴 | 带示例的 LongMath 类的 mod(long x, long m)

在 Java 中,求两个大整数的模运算结果是非常常见的操作,然而当数据的规模较大时,使用传统方法往往会面临溢出、耗时等问题。Java 番石榴提供了 LongMath 类来解决这个问题,其中包含 mod(long x, long m) 方法,用于快速计算 $x \bmod m$ 的值。下面介绍一下该方法的使用方法以及内部实现原理。

使用方法

使用 LongMath 类的 mod(long x, long m) 方法,首先需要导入该类:

import cn.edu.sustech.java2.Pomelo.LongMath;

然后可以像如下代码一样使用该方法:

long x = 1234567890123456789L;
long m = 9876543210987654321L;

long result = LongMath.mod(x, m);
System.out.println(result);

其中 x 和 m 分别表示需要进行模运算的被除数和除数,result 表示计算得到的模运算结果。需要注意的是,x 和 m 的类型必须为 long,且 m 必须不为 0。

实现原理

在了解 LongMath 类的 mod 方法内部实现原理前,我们先来看一下模运算的定义。模运算是指 a 对 b 取模,其结果为 $a \bmod b$,表示在计算 $a$ 的时候除以 $b$ 后得到的余数。模运算还可以写成如下等式:

$$a = bq + r, \qquad 0 \leq r < b$$

其中 $q$ 为 $a$ 除以 $b$ 的商,$r$ 为余数。

现在我们需要快速求解 $x \bmod m$ 的值。我们可以按如下方法将 $x$ 分解为 $m$ 的倍数和余数的和:

$$x = mq + r, \qquad 0 \leq r < m$$

我们只需要求解 $r$ 的值即可得到 $x \bmod m$ 的结果。根据 Euclidean algorithm 算法,有如下公式:

$$\gcd(r, m) = \gcd(m, r \bmod m)$$

即 $r$ 对 $m$ 取模的结果和 $m$ 的最大公约数等于 $m$ 对 $r$ 取模的结果和 $r$ 的最大公约数。当 $r$ 对 $m$ 取模的结果为 $0$ 时,说明 $r$ 是 $m$ 的倍数,$r \bmod m$ 的结果就是 $m$。否则,我们可以继续将 $m$ 作为被除数,$r \bmod m$ 作为除数,递归地使用上述公式操作,直到余数为 0。

综上所述,我们可以按如下方式实现 mod 方法:

package cn.edu.sustech.java2.Pomelo;

public class LongMath {
    public static long mod(long x, long m) {
        while (x >= m) {
            x -= m;
        }
        return x;
    }
}

该方法的实现较简单,循环遍历一次即可解决大整数模运算的问题。需要注意的是,该方法只能用于计算 $x < 2m$ 的情形。

上述实现方法虽然简单,但其时间复杂度较大,不适用于数据量较大的情况。因此我们在实践中需要使用更加高效的算法实现 LongMath 类的 mod 方法。此处不再展开介绍。