处理3.3.7 Carmichael函数

时间:2018-11-04 20:57:31

标签: processing modulo

因此,我试图在处理某些我正在使用的RSA加密东西时使用carmichael函数,但是模函数似乎给出了许多错误的答案。 这是我的代码:

int carmichael(int n) {
  int checkIndex = 0;
  int m = 1;
  ArrayList<Integer> coprimes = findCoprimesLessThan(n);

  println(coprimes);

  for(m = 1; m < 50; m++){
    for(checkIndex = 0; checkIndex < coprimes.size(); checkIndex++){
      int a = coprimes.get(checkIndex);
      float mod = pow(a, m) % n;

      println(a, m, n, mod, pow(a, m), pow(a, m) % n);

      if (mod == 1) {
        continue;
      }
      if (mod != 1){
        break;
      }
      return m;
    }
  }
  return 1;
}

对于说31的输入,它会永远循环(出于这个原因,我将其停止在100上,因此如果它遍历全部100而没有找到任何东西,它只会输出1)应该给出30。我相信我已将其范围缩小到对大数不起作用的模运算,因为这似乎是问题所在,例如: 当a = 3,m = 30,n = 31时,我的println语句给出了这一点:

3 30 31 18.0 2.05891136E14 18.0

,所有这些都是正确的 模,应该为1.0时给出18.0。无论如何,我不确定如何解决这个问题,甚至像这样“手动模数”:

while(mod >= n){
  mod-= n;
}

导致完全相同的问题。我对carmichael函数所做的所有研究都使我感到困惑,或者here毫无帮助。

1 个答案:

答案 0 :(得分:0)

我的猜测是您正在达到浮动精度的极限。

浮点值只能跟踪一定的精度。尝试运行此示例程序:

float one = 123456789;
float two = one + 1;
println(one == two);

您希望此命令可以打印false,但是如果运行它,则会看到它打印的是true。这是因为我们超出了精度的范围。

要解决此问题,您可以升级到double类型。双精度值具有相同的问题,但精度更高。

double one = 123456789;
double two = one + 1;
println(one == two);

默认情况下,返回到您的代码,Processing将所有内容都视为float值。在大多数情况下都可以,但是如果需要很高的精度,则最好切换到double值。

int a = 3;
int m = 30;
int n = 31;

double p = Math.pow(a, m);
println(p);

double mod = p % n;

println(mod);

请注意,我使用的是Math.pow()而不是pow()Math.pow()函数来自Java,并接受并返回double值而不是float值。

(顺便说一下,这是我在评论中讨论的示例程序的类型。)