Java中数组寻址的时间复杂度差异

时间:2011-10-04 20:18:31

标签: java time complexity-theory

因此,在编码涉及时间复杂度的图像处理功能时,我有一个随机的问题。以下是我原始的代码片段:

    long start = System.currentTimeMillis();

    for (int i = 0; i < newWidth; i++) {
        for (int j = 0; j < newHeight; j++) {

            double x = i * scaleX;
            double y = j * scaleY;

            double xdiff = x - (int) x;
            double ydiff = y - (int) y;

            int xf = (int) Math.floor(x);
            int xc = (int) Math.ceil(x);
            int yf = (int) Math.floor(y);
            int yc = (int) Math.ceil(y);

            double out = inputArray[xf][yf] * (1 - xdiff) * (1 - ydiff)
                    + inputArray[xc][yf] * xdiff * (1 - ydiff)
                    + inputArray[xf][yc] * (1 - xdiff) * ydiff
                    + inputArray[xc][yc] * xdiff * ydiff;

            outputArray[i][j] = (int) out;
        }
    }

    long elapsed = System.currentTimeMillis() - start;
    System.out.println("Time used: " + elapsed);

在推出该代码后,我想知道是否更快不为楼层和天花板值创建4个临时变量,而是直接在数组索引中计算它们。所以我这样修改了它:

    long start = System.currentTimeMillis();

    for (int i = 0; i < newWidth; i++) {
        for (int j = 0; j < newHeight; j++) {

            double x = i * scaleX;
            double y = j * scaleY;

            double xdiff = x - (int) x;
            double ydiff = y - (int) y;

            double out = inputArray[(int) Math.floor(x)][(int) Math.floor(y)] * (1 - xdiff) * (1 - ydiff)
                    + inputArray[(int) Math.ceil(x)][(int) Math.floor(y)] * xdiff * (1 - ydiff)
                    + inputArray[(int) Math.floor(x)][(int) Math.ceil(y)] * (1 - xdiff) * ydiff
                    + inputArray[(int) Math.ceil(x)][(int) Math.ceil(y)] * xdiff * ydiff;

            outputArray[i][j] = (int) out;
        }
    }

    long elapsed = System.currentTimeMillis() - start;
    System.out.println("Time used: " + elapsed);

我期待后者更快(因为您不必写入临时变量然后访问它)但事实证明,后者至少比前一代码慢2.5倍。使用的测试用例是3x zoom 1024x768 img。

前代码:使用时间:812 后来的代码:使用的时间:2140

那么时差的原因是什么?

7 个答案:

答案 0 :(得分:6)

你在后面的代码中有8个Math.floor()/ Math.ceil()计算而不是4.那就是问题。

计算比为局部变量分配空间慢得多。

答案 1 :(得分:3)

问:在第一种情况下你有多少次打电话给“地板”和“ceil”?第二种情况? ;)

问:我想知道这是否比第一种情况更快:

    long start = System.currentTimeMillis();

    for (int i = 0; i < newWidth; i++) {
        double x = i * scaleX;
        double xdiff = x - (int) x;
        int xf = (int) Math.floor(x);
        int xc = (int) Math.ceil(x);
        for (int j = 0; j < newHeight; j++) {
            double y = j * scaleY;
            double ydiff = y - (int) y;

            int yf = (int) Math.floor(y);
            int yc = (int) Math.ceil(y);

            double out = inputArray[xf][yf] * (1 - xdiff) * (1 - ydiff)
                    + inputArray[xc][yf] * xdiff * (1 - ydiff)
                    + inputArray[xf][yc] * (1 - xdiff) * ydiff
                    + inputArray[xc][yc] * xdiff * ydiff;

            outputArray[i][j] = (int) out;
        }
    }

    long elapsed = System.currentTimeMillis() - start;
    System.out.println("Time used: " + elapsed);

答案 2 :(得分:2)

floorceil会产生性能费用。

你的第二个案件经常召唤他们两次。

答案 3 :(得分:2)

在第二个中你重复计算。通过在第一个示例中的变量中捕获它,可以避免重复计算。

答案 4 :(得分:2)

后者可能会变慢,因为它做得更多。设置一个临时变量是微不足道的,但计算地板和ceil可能会非常昂贵。

BTW:当x为正数时,(int) Math.floor(x)(int) x相同,因此您无需计算两次。

此外,在这种情况下,您可以假设xc = xf + 1y

也是如此

答案 5 :(得分:2)

与Math.floor和Math.ceil相比,保存和查找局部变量的微小操作变得苍白无力。此外,您在第二个片段中更频繁地转换为int。

答案 6 :(得分:1)

您可以简单地将double转换为int,而不是使用Math.floor()。它会更快。

而不是:

inputArray[(int) Math.floor(x)]

只是:

inputArray[(int) x]