我正在尝试用Java实现RSA算法。
当您查看此页面时:http://en.wikipedia.org/wiki/RSA_(algorithm)#A_working_example您可以看到此计算:
c = 65 ^ 17 mod 3233 = 2790
当我使用这个Java代码时:
double valc = Math.pow(65, 17) % 3233;
System.out.println("Expected = 2790, computed = " + valc);
结果是:
Expected = 2790, computed = 887.0
我做错了什么?
答案 0 :(得分:5)
您假设浮点计算精确到疯狂的数字位数,而不是。 pow
不是计算65^17
的正确方法。你真的想做
65 * 65 * 65 ...
所以
result = 1;
for(ii = 0; ii < 17; ii++) result *= 65;
这将导致精度损失(它的位数多于内置类型可以表示的数字)。
查看模数计算可以显着简化这些计算的方式。请参阅示例https://math.stackexchange.com/questions/36318/modulo-arithmetic-with-big-numbers
它表明您可以执行上述操作:
result = 1;
for(ii = 0; ii < 17; ii++) {
result *= 65;
result = result % 3233;
}
有比这更有效的方法 - 但这会给你正确的结果。见http://jdoodle.com/a/2l
答案 1 :(得分:2)
Double没有足够的计算范围。尝试像BigInteger这样的
public static void main(String args[]) {
BigInteger valc = new BigInteger("65");
valc = valc.pow(17);
valc = valc.mod(new BigInteger("3233"));
System.out.println("Expected = 2790, computed = " + valc);
}
哪个输出
Expected = 2790, computed = 2790
答案 2 :(得分:1)
double没有足够的位(52)来精确地保持65 ^ 17.需要103位:
BigInteger.valueOf(65).pow(17).bitLength() == 103
而是使用BigInteger,它使用任意数量的位来表示精确的整数,仅受内存的限制:
BigInteger.valueOf(65).pow(17).mod(BigInteger.valueOf(3233)) == 2790
答案 3 :(得分:0)
如果您确实需要管理真实数字或有理数字,则应使用double
。在这种情况下,您不需要它。使用BigInteger
并查看here。