当前位置: 首页 > 面试题库 >

用于转换double [] []矩阵的紧凑流表达式

侯沈义
2023-03-14
问题内容

我想以double[][]最紧凑和最有效的表达方式转置矩阵。现在我有这个:

public static Function<double[][], double[][]> transpose() {
    return (m) -> {
        final int rows = m.length;
        final int columns = m[0].length;
        double[][] transpose = new double[columns][rows];
        range(0, rows).forEach(r -> {
            range(0, columns).forEach(c -> {
                transpose[c][r] = m[r][c];
            });
        });
        return transpose;
    };
}

有什么想法吗?


问题答案:

你可以有:

public static UnaryOperator<double[][]> transpose() {
    return m -> {
        return range(0, m[0].length).mapToObj(r ->
            range(0, m.length).mapToDouble(c -> m[c][r]).toArray()
        ).toArray(double[][]::new);
    };
}

此代码不使用,forEach而是使用mapToObj并将mapToDouble每行映射到它们的转置。由于返回类型相同,因此我也更改Function<double[][], double[][]>UnaryOperator<double[][]>

但是,像assylias的答案中那样具有简单的for循环可能不会更有效。

样例代码:

public static void main(String[] args) {
    double[][] m = { { 2, 3 }, { 1, 2 }, { -1, 1 } };
    double[][] tm = transpose().apply(m);
    System.out.println(Arrays.deepToString(tm)); // prints [[2.0, 1.0, -1.0], [3.0, 2.0, 1.0]]
}

我已经实现了一个JMH基准测试,可以比较上面的代码,for循环版本和上面的代码并行运行。使用大小分别为100、1000和3000的随机平方矩阵调用这三种方法。结果是,对于较小的矩阵,for循环版本更快,但是对于较大的矩阵,并行Stream解决方案的性能确实更好(
Windows 10,JDK 1.8.0_66,i5-3230M @ 2.60 GHz ):

Benchmark                           (matrixSize)  Mode  Cnt    Score    Error  Units
StreamTest.forLoopTranspose                  100  avgt   30    0,026 ±  0,001  ms/op
StreamTest.forLoopTranspose                 1000  avgt   30   14,653 ±  0,205  ms/op
StreamTest.forLoopTranspose                 3000  avgt   30  222,212 ± 11,449  ms/op
StreamTest.parallelStreamTranspose           100  avgt   30    0,113 ±  0,007  ms/op
StreamTest.parallelStreamTranspose          1000  avgt   30    7,960 ±  0,207  ms/op
StreamTest.parallelStreamTranspose          3000  avgt   30  122,587 ±  7,100  ms/op
StreamTest.streamTranspose                   100  avgt   30    0,040 ±  0,003  ms/op
StreamTest.streamTranspose                  1000  avgt   30   14,059 ±  0,444  ms/op
StreamTest.streamTranspose                  3000  avgt   30  216,741 ±  5,738  ms/op

基准代码:

@Warmup(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(3)
public class StreamTest {

    private static final UnaryOperator<double[][]> streamTranspose() {
        return m -> {
            return range(0, m[0].length).mapToObj(r ->
                range(0, m.length).mapToDouble(c -> m[c][r]).toArray()
            ).toArray(double[][]::new);
        };
    }

    private static final UnaryOperator<double[][]> parallelStreamTranspose() {
        return m -> {
            return range(0, m[0].length).parallel().mapToObj(r ->
                range(0, m.length).parallel().mapToDouble(c -> m[c][r]).toArray()
            ).toArray(double[][]::new);
        };
    }

    private static final Function<double[][], double[][]> forLoopTranspose() {
        return m -> {
            final int rows = m.length;
            final int columns = m[0].length;
            double[][] transpose = new double[columns][rows];
            for (int r = 0; r < rows; r++)
                  for (int c = 0; c < columns; c++++)
                    transpose[c][r] = m[r][c];
            return transpose;
        };
    }

    @State(Scope.Benchmark)
    public static class MatrixContainer {

        @Param({ "100", "1000", "3000" })
        private int matrixSize;

        private double[][] matrix;

        @Setup(Level.Iteration)
        public void setUp() {
            ThreadLocalRandom random = ThreadLocalRandom.current();
            matrix = random.doubles(matrixSize).mapToObj(i -> random.doubles(matrixSize).toArray()).toArray(double[][]::new);
        }

    }

    @Benchmark
    public double[][] streamTranspose(MatrixContainer c) {
        return streamTranspose().apply(c.matrix);
    }

    @Benchmark
    public double[][] parallelStreamTranspose(MatrixContainer c) {
        return parallelStreamTranspose().apply(c.matrix);
    }

    @Benchmark
    public double[][] forLoopTranspose(MatrixContainer c) {
        return forLoopTranspose().apply(c.matrix);
    }

}


 类似资料:
  • 问题内容: 任何人都具有可以用以下形式在Java中转置Matrix的功能: 我有这样的功能: 但是在某处是错误的。 问题答案:

  • 我尝试创建一个使用压缩和删除的Kafka主题配置,以实现以下目标: 在保留期限内,保留密钥的最新版本 在保留期之后,要删除的任何早于时间戳的消息 当我在测试中将其设置为较小的量时,例如20mins、1hr等,我可以正确地看到数据在保留期后被修剪,只需调整主题上的。 我可以看到数据正按照预期的那样被正确压缩,但是如果我从一开始就阅读主题,那么在10天的保留期之后,比10天早得多的数据仍然存在。这么长

  • 问题内容: 我想将图像的颜色基础从RGB更改为其他颜色。我有一个要应用于每个像素的RGB的矩阵M,我们可以将其定义为x ij。 我目前正在迭代NumPy图像的每个像素并手动计算Mx ij。我什至无法对它们进行矢量化处理,因为RGB是1x3而不是3x1数组。 有一个更好的方法吗?也许是OpenCV或NumPy中的函数? 问题答案: 记不清执行此操作的规范方法(可能避免了转置),但这应该可行: 如果是

  • 变换矩阵 之前三节所说的坐标变换的三种方式——平移translate(),缩放scale(),以及旋转rotate()都可以通过transform()做到。 在介绍矩阵变换transform()前,我们来说一说什么是变换矩阵。 以上是Canvas中transform()方法所对应的变换矩阵。而此方法正是传入图中所示的六个参数,具体为context.transform(a,b,c,d,e,f)。 各

  • 本文向大家介绍如何使用HTML5创建转换矩阵?,包括了如何使用HTML5创建转换矩阵?的使用技巧和注意事项,需要的朋友参考一下 HTML5 canvas提供了允许直接修改转换矩阵的方法。转换矩阵最初必须是身份转换。然后可以使用转换方法对其进行调整。 S号 方法和说明 1 变换(m11,m12,m21,m22,dx,dy) 此方法更改转换矩阵以应用参数指定的矩阵。 2 setTransform(m1

  • 我目前正在将原始矩阵转换为光栅以使用焦距函数,然后我想将光栅转换回矩阵。但是,当我尝试将光栅函数用作时,出现了一条错误消息。矩阵()。即使有这个非常简单的例子: 以下是我得到的: 如果(!is.null(names(x)))列表(names(x),,则数组(x,c(length(x),1L)中出错: “dimnames”[1]的长度不等于数组范围 我正在使用RstuIO、R版本3.4.0和、和库。