计算一个*一个没有溢出的模数n
Calculate a*a mod n without overflow
我需要计算a*a
mod n
但a
相当大,导致我平方时溢出。执行((a % n)*(a % n)) % n
不起作用,因为 (n-1)2 可能会溢出。这是C++,我正在使用int64_t
编辑:
示例值:a = 821037907258 和 n = 800000000000,如果平方,则会溢出。
我正在使用 DevCPP,我已经尝试让大整数库工作无济于事。
编辑 2:
不,这些数字没有模式。
如果您无法使用大整数库,并且没有本机uint128_t
(或类似),则需要手动执行此操作。
一种选择是将a
表示为两个 32 位量的总和,即 a = 2 32 b + c,其中 b 包含 32 msb,c 包含 32 个 lsb。 然后平方是一组四个交叉乘法;每个结果都保证适合 64 位类型。 然后,在重新组合各个项时进行模运算(仔细考虑重新对齐所有项所需的偏移)。
我知道你不再需要这个,并且有一个替代解决方案,但我想添加一个替代方法来实现它。它提供了两种不同的技术:双精度和加法算法,以及使用溢出检测处理mod(a + b, n)
的方法。
双倍加法算法通常用于无法乘法或直接计算成本太高的领域(例如椭圆曲线),但我们可以采用它来处理它,而不是在我们的情况下处理溢出。
以下代码可能比接受的解决方案慢(即使您对其进行了优化),但如果速度不是关键,为了清楚起见,您可能更喜欢它。
unsigned addmod(unsigned x, unsigned y, unsigned n)
{
// Precondition: x<n, y<n
// If it will overflow, use alternative calculation
if (x + y <= x) x = x - (n - y);
else x = (x + y) % n;
return x;
}
unsigned sqrmod(unsigned a, unsigned n)
{
unsigned b;
unsigned sum = 0;
// Make sure original number is less than n
a = a % n;
// Use double and add algorithm to calculate a*a mod n
for (b = a; b != 0; b >>= 1) {
if (b & 1) {
sum = addmod(sum, a, n);
}
a = addmod(a, a, n);
}
return sum;
}
法a * b % m
的双加实现,没有溢出,无论 a、b 和 m 的大小如何。
(请注意,res -= m
行和temp_b -= m
行依赖于 64 位无符号整数溢出才能给出预期的结果。这应该没问题,因为无符号整数溢出在 C 和 C++ 中定义得很好。因此,使用无符号整数类型非常重要。
uint64_t mulmod(uint64_t a, uint64_t b, uint64_t m) {
uint64_t res = 0;
uint64_t temp_b;
/* Only needed if b may be >= m */
if (b >= m) {
if (m > UINT64_MAX / 2u)
b -= m;
else
b %= m;
}
while (a != 0) {
if (a & 1) {
/* Add b to res, modulo m, without overflow */
if (b >= m - res) /* Equiv to if (res + b >= m), without overflow */
res -= m;
res += b;
}
a >>= 1;
/* Double b, modulo m */
temp_b = b;
if (b >= m - b) /* Equiv to if (2 * b >= m), without overflow */
temp_b -= m;
b += temp_b;
}
return res;
}
这是我对另一个类似问题的另一个答案的修改。
您可以自己实现乘法,每次运行添加 n 个,并立即修改结果。
我真的认为((a % n)*(a % n)) % n
应该适用于正整数。 你为什么认为它不起作用? 你有反例吗? 如果 n 可以为负数,则%
运算符未定义。
- 如何创建一个函数来计算并返回平均值、最大值和最小值
- 不计算一个范围内的完美数
- 3-3. 编写一个程序来计算每个不同单词在其输入中出现的次数
- 我的目标是编写一个程序来计算和存储字符串在字符数组中出现的位置
- 从另一个静态常量数组初始化静态常量数组(只需少量计算)
- 为什么我必须添加一个小数才能在C++中正确计算此数学
- 视觉我希望一个函数在另一个函数C++中进行计算
- 计算单词中的音节数,但考虑到单词中彼此相邻的任何元音都算作一个音节
- 如何使用条件计算 3D 网格中从一个点到另一个点的所有路径
- 计算在同一位置至少包含一个常用字符的不同字符串对
- 返回一个计算了参数的函数
- 我在c++中遇到了一个奇怪的错误,其中一个计算2个小整数加法的语句溢出到一个长值中
- 在C++中,是否可以编写一个条件的lambda,即只是一个计算结果为真或假的条件
- 你能在C++中制作一个计算的goto吗?
- 为什么需要 FPU 重置以防止 NaN 结果传播到下一个计算结果?
- 创建一个C++计算奇数、偶数和零数的程序
- 在C++中是否已经为文件系统迷你过滤器驱动程序编写了一个计算MD5哈希的函数
- 编写一个计算n的子程序.使用此子程序时,制作一个计算(a+b)的程序
- 将数组从C/C++传递给Fortran,并返回一个计算的数组
- 扩展一个计算线路频率的程序