【问题标题】:Modular Exponentiation模幂
【发布时间】:2014-07-19 02:35:04
【问题描述】:

我正在尝试使用this method 来分解具有大指数的基数,因为标准 C++ 库中的数据类型不会存储那么大的数字。

问题出在最后一个循环中,我使用fmod() 函数来修改我的大数。答案应该是 1,但我得到 16。有人看到问题了吗?

#include <iostream>
#include <vector>
#include <math.h>

using namespace std;

typedef vector<int> ivec;
ivec binStorage, expStorage;

void exponents()
{
    for (int j=binStorage.size(); j>=0; j--)
        if(binStorage[binStorage.size()-j-1]!=0)
            expStorage.push_back(pow(2, j));
}

void binary(int number)
{
    int remainder;

    if(number <= 1)
    {
        cout << number;
        return;
    }

    remainder = number%2;
    binary(number >> 1);
    cout << remainder;
    binStorage.push_back(remainder);
}

int main()
{
    int num = 117;
    int message = 5;
    int mod = 19;
    int prod = 1;
    binary(num);
    cout << endl;
    exponents();

    cout << "\nExponents: " << endl;
    for (int i=0; i<expStorage.size(); i++)
        cout << expStorage[i] << " " ;

    cout << endl;
    cout << "\nMessage" << "-" << "Exponent" << endl;
    for (int i=0; i<expStorage.size(); i++)
    {
        cout << message << "-" << expStorage[i] << endl;
        prod *= fmod(pow(message, expStorage[i]), mod);
    }
    cout << "\nAnswer: " << fmod(prod, mod) << endl;
    return 0;
}

这是我的结果:

1110101

Exponents:
64 32 16 4 1

Message-Exponent
5-64
5-32
5-16
5-4
5-1

Answer: 16

Process returned 0 (0x0)   execution time : 0.085 s
Press any key to continue.

编辑: 这是问题循环。

for (int i=0; i<expStorage.size(); i++)
    {
        cout << message << "-" << expStorage[i] << endl;
        prod *= fmod(pow(message, expStorage[i]), mod);
    }

【问题讨论】:

  • 您不能将其缩小到 一个 对输入和输出吗?我确信我们不需要整个程序和所有那些不相关的计算。
  • 我把范围缩小到问题循环
  • 在某些时候会做 5 的 64 次方吗?即溢出,它错过了链接中的替换点
  • 我并不是想让你把一个随机循环扔给我们。我的意思是让你展示一个testcase,一个只包含包含的程序,一个小的main,一个或两个常量输入值,有问题的函数调用,也许还有一些输出来证明输出不是它应该的是。这应该是您的第一个调试步骤。
  • 改用modpow

标签: c++ math modular


【解决方案1】:

您发布的算法是modular exponentiation algorithm。按照您发布的链接中的步骤,算法简化为以下代码:

#include <iostream>
#include <cmath>

// B : Base
// E : Exponent
// M : Modulo
constexpr int powermod(int const B, int const E, int const M) {
  return ((E > 1) ? (powermod(B, E / 2, M) * powermod(B, E / 2, M) * powermod(B, E % 2, M)) % M
                  : (E == 0) ? 1 : B % M);
}

int main() {
  int const e = 117;
  int const b = 5;
  int const m = 19;

  std::cout << "Answer: " << powermod(b, e, m) << std::endl;

  return 0;
}

注意,我使用了constexpr。如果您的编译器不支持它,您可以将其删除。使用constexpr 并假设输入参数是常量表达式,如上面的示例,幂指数的计算将在编译时进行。

现在关于您发布的代码:

  • 似乎fmod doesn't work well with big numbers 喜欢(5^325^64)并给出错误的结果。

  • 另外,您的代码存在编译错误和运行时错误,因此我更正了它。

  • 我编写了一个基于递归计算模数的算法。基本上是我上面发布的算法的变体,安全防护能力为 4。(参见下面的函数safemod()):


#include <iostream>
#include <cmath>
#include <vector>

using namespace std;

typedef vector<int> ivec;

// B : Base     (e.g., 5)
// E : Exponent (e.g., 32)
// M : Modulo   (e.g., 19)
double safemod(double B, double E, double M) {
  return ((E > 4) ? fmod(safemod(B, E / 2, M) * safemod(B, E / 2, M), M)
    :
    fmod(pow(B, E), M));
}

void exponents(ivec const &binStorage, ivec &expStorage) {
  int j(pow(2.0, binStorage.size() - 1));
  for (vector<int>::const_iterator it(binStorage.begin()), ite(binStorage.end()); it != ite; ++it) {
    if (*it != 0) expStorage.push_back(j);
    j /= 2;
  }
}

void binary(int const number, ivec &binStorage) {
  if (number > 0) {
    int remainder = number % 2;
    binary(number / 2, binStorage);
    binStorage.push_back(remainder);
  }
}

int main() {
  int num     = 117;
  int message = 5;
  int mod     = 19;
  int prod    = 1;
  ivec binStorage, expStorage;

  binary(num, binStorage);
  for (size_t i(0); i < binStorage.size(); ++i) cout << binStorage[i];
  cout << endl;

  exponents(binStorage, expStorage);
  cout << "\nExponents: " << endl;
  for (size_t i(0); i<expStorage.size(); ++i) cout << expStorage[i] << " ";
  cout << endl;

  cout << "\nMessage" << "-" << "Exponent" << endl;
  for (size_t i(0); i<expStorage.size(); ++i) {
    cout << message << "-" << expStorage[i] << endl;
    prod *= safemod(message, expStorage[i], mod);
  }

  cout << "\nAnswer: " << fmod(prod, mod) << endl;

  return 0;
}

输出:

1110101

指数: 64 32 16 4 1

消息指数

5 - 64

5 - 32

5 - 16

5 - 1

答案:1

【讨论】:

  • 我不断收到错误消息:“int”之前的预期主表达式。那是什么?
  • @user3519448 你用的是什么编译器?
  • @user3519448 查看更新后的答案。您的代码中有错误,例如超出范围等。
猜你喜欢
  • 2018-01-15
  • 2014-08-21
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 2020-09-11
相关资源
最近更新 更多