因此,我试图在处理某些我正在使用的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毫无帮助。
答案 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
值。
(顺便说一下,这是我在评论中讨论的示例程序的类型。)