如何解决模幂C ++的问题
我正在尝试对大值(最多64位)执行模幂运算,并为此编写了以下函数:
uint64_t modularExp(uint64_t num,uint64_t exp,uint64_t mod)
{
string expBits = bitset<64>(exp).to_string();
expBits = expBits.substr(expBits.find("1")+1);
string operations = "";
uint64_t result = num;
for (int i = 0; i < expBits.length(); ++i)
{
result = (uint64_t)pow(result,2) % mod;
if (expBits[i] == '1')
result = (result * num) % mod;
}
return result;
}
这对于较小的数字(8位或更少)有效,但对于较大的数字,即使它们在64位范围内,结果也会显示错误。
此外,当mod的值超过4294967296(最大32位值)时,结果仅为零。我怀疑pow函数可能在此问题中起作用,但是我不能确定。
任何建议将不胜感激。
解决方法
首先,一些一般性建议:
- 使用整数时最好不要使用字符串,因为使用字符串的操作要慢得多,并且可能会成为性能瓶颈。还不清楚当涉及字符串时实际上在做什么。
- 您不应该将
std::pow
与整数一起使用,因为它对浮点数进行运算并且会失去精度。
对于主要问题,作为一种解决方法,可以使用此O(log^2(n))
解决方案,该解决方案应适用于最大63位的参数(因为它只使用2的加法和乘法)。请注意,如果只是以小到大的顺序遍历位,那么所有这些字符串魔术都是不必要的:
#include <cstdint>
uint64_t modular_mul(uint64_t a,uint64_t b,uint64_t mod) {
uint64_t result = 0;
for (uint64_t current_term = a; b; b >>= 1) {
if (b & 1) {
result = (result + current_term) % mod;
}
current_term = 2 * current_term % mod;
}
return result;
}
uint64_t modular_pow(uint64_t base,uint64_t exp,uint64_t mod) {
uint64_t result = 1;
for (uint64_t current_factor = base; exp; exp >>= 1) {
if (exp & 1) {
result = modular_mul(result,current_factor,mod);
}
current_factor = modular_mul(current_factor,mod);
}
return result;
}
此外,在gcc中,某些目标可以使用(非标准)__uint128_t
。 (可用于将modular_mul
替换为普通乘法)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。