Math.pow()使用不同的输入返回相同的结果

时间:2017-03-27 00:22:38

标签: java

我有两个空数组和一些变量:

static int p = 41;
static int q = 67;
static int d = 83;
static int n = p * q;

static int[] encryptedBlocks = new int[charArray.length];
static int[] decryptedArray = new int[charArray.length];

其中第一个填充了以下内容(我已经检查过,确实如此):

1573
1978
385
1092
1022
857
856
1387
225
606
2293
1339
1630

第二个数组我试图在for循环中填充方程的结果:

for (int i = 0; i < encryptedBlocks.length; i++) {
            int M = (int)Math.pow(encryptedBlocks[i], d) % n;
            decryptedArray[i] = M;
        }

问题是我为每次迭代得到了M的相同结果。我对于发生了什么完全无能为力:

2662
2662
2662
2662
2662
2662
2662
2662
2662
2662
2662
2662
2662

以防万一我检查encryptedBlocks[i]确实是每次迭代的下一个值,它就是。我遗漏了与使用intMath.pow()相关的内容吗?

encryptedBlocks[i]dn的前两个迭代值:

1573 83 2747 
1978 83 2747

6 个答案:

答案 0 :(得分:2)

在您的代码行中

int M = (int)Math.pow(encryptedBlocks[i], d) % n;

您正在计算Math.pow(encryptedBlocks [i],d),然后将其转换为int,然后在int结果上使用modulo m。您可能想要做的只是在完成所有数学运算后才转换为int:

int M = (int) (Math.pow(encryptedBlocks[i], d) % n);

产生:

1147 2564 1457 2351 2414 982 1073 2480 923 1526 704 427 235

用于给定的输入数据。

答案 1 :(得分:2)

如上所述here

  

转换优先于除法运算

因此,正如我在评论中提到的,你必须替换它:

int M = (int)Math.pow(encryptedBlocks[i], d) % n;

有了这个:

int M = (int)(Math.pow(encryptedBlocks[i], d) % n);

答案 2 :(得分:1)

只是优先级错误
  将此int M = (int)Math.pow(encryptedBlocks[i], d) % n;更改为int M = (int)(Math.pow(encryptedBlocks[i], d) % n);

答案 3 :(得分:1)

是的,你正在向早期转换为int,这导致输出始终相同。您可以在下面的输出中查看。

package test;

public class MathPow {

    static int p = 41;
    static int q = 67;
    static int d = 83;
    static int n = p * q;

    static int[] encryptedBlocks = {1573,
            1978,
            385,
            1092,
            1022,
            857,
            856,
            1387,
            225,
            606,
            2293,
            1339,
            1630};
    static int[] decryptedArray = new int[13];

    public static void main (String []args){

        for (int i = 0; i < encryptedBlocks.length; i++) {
            double power = Math.pow(encryptedBlocks[i], d);
            System.out.println("Power : "+power);
            double pwer = power % n;
            int M = (int)pwer;
            decryptedArray[i] = M;
            System.out.println("M : "+M);
        }

    }

}

在最后完成转换为int时的输出。

Power : 2.1305119658955046E265
M : 1147
Power : 3.8617294369074443E273
M : 2564
Power : 3.9195891716526933E214
M : 1457
Power : 1.4875753889539146E252
M : 2351
Power : 6.087295034019223E249
M : 2414
Power : 2.7378409793777127E243
M : 982
Power : 2.4849775423187883E243
M : 1073
Power : 6.199351610800489E260
M : 2480
Power : 1.702742606656262E195
M : 923
Power : 8.815111415893474E230
M : 1526
Power : 8.194765730142982E278
M : 704
Power : 3.332636081546012E259
M : 427
Power : 4.0885674380373943E266
M : 235

在Math.pow操作之后完成转换时输出。

Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662
Power : 2.147483647E9
M : 2662

您可以看到功率运算结果相同,因此M也相同。

答案 4 :(得分:1)

电源操作的结果太大而无法存储在整数中。仅1573 ^ 83是一个122位数字,你在计算功率后正在进行mod操作,因此它已经溢出。

如果不考虑性能,可以使用BigInteger类。这应该有效:

BigInteger bigN = BigInteger.valueOf(n);
for (int i = 0; i < encryptedBlocks.length; i++) {
    BigInteger M = BigInteger.valueOf(encryptedBlocks[i]).pow(d).mod( bigN );
    decryptedArray[i] = Integer.valueOf(M.toString());
}
for(int i : decryptedArray) System.out.println(i);

但是,BigInteger操作有点慢。如果您更喜欢更快的解决方案,您可以实现自己的电源功能,这样您就可以在接近溢出整数值时执行mod操作。

答案 5 :(得分:1)

您的问题在括号中。这就是编译器看到你写的内容的方式:

((int) Math.pow(encryptedBlocks[i], d)) % n

这是微妙的,但是在采用模数之前,它正在向int施放。通常情况下,这不会产生任何影响,但在您的情况下,Math.pow返回如此大的数字,将其转换为int将其截断为2147483647 int可以存储的最大值,然后它将返回将返回2662的模块。

现在,要获得正确答案,我们需要做的就是确保它首先计算模数:

(int) (Math.pow(encryptedBlocks[i], d) % n)