Fortran实现numpy.roll函数的最优方式及多余行删除方法咨询
Fortran实现类似numpy.roll的功能问题解答
背景:numpy.roll的功能
Python的numpy.roll函数可沿指定轴滚动数组,示例如下:
from numpy import roll, array x = array([[1,0,2],[2,1,9],[5,5,1]]) print(roll(x, 1, axis=0))
运行后矩阵x被转换为:
array([[5, 5, 1], [1, 0, 2], [2, 1, 9]])
Fortran实现尝试
尝试通过切片矩阵行并附加到原矩阵的方式实现该功能,代码如下:
program myfun implicit none integer, parameter :: N=3 real, dimension(N,N) :: m integer :: i, j m = 0 do i = 1, N m(i, i) = 1.0 enddo m(3,1) = 2 m(3,2) = 9 m(1,3) = 5 m(1,2) = 2 m(2,3) = 5 print *, '', [m(:,N), m] end program myfun
运行后得到的结果多出一行:
[5, 5, 1] [1, 0, 2] [2, 1, 9] [5, 5, 1] <- 需要删除此行(如何操作?)
问题解答
1. 这是不是最优实现方式?
这种拼接切片后再删除行的方式并非最优。原因在于Fortran是列主序存储,直接拼接容易出现维度匹配错误,且会生成不必要的临时数组,降低效率。更高效的方式是直接通过切片赋值构造目标数组,无需后续删除操作。
2. 正确的实现方式(避免多余行)
要实现沿轴0(行方向)滚动1次的效果,本质是把矩阵的最后一行移到开头,拼接剩余的前N-1行。由于Fortran数组拼接是按列优先,需要用reshape确保维度正确,代码示例如下:
program myfun implicit none integer, parameter :: N=3 real, dimension(N,N) :: m, rolled_m integer :: i, j m = 0 do i = 1, N m(i, i) = 1.0 enddo m(3,1) = 2 m(3,2) = 9 m(1,3) = 5 m(1,2) = 2 m(2,3) = 5 ! 沿轴0滚动1次:将最后一行移到开头,拼接前N-1行 rolled_m = reshape([m(N,:), m(1:N-1,:)], [N, N]) ! 逐行打印结果 do i = 1, N print *, rolled_m(i,:) enddo end program myfun
运行此代码会直接得到正确的3×3矩阵,无需处理多余行。如果要支持任意滚动步数,可以通过计算偏移量来调整切片范围,比如滚动k步时,取最后k行拼接前N-k行。
内容的提问来源于stack exchange,提问作者Medulla Oblongata
相关产品推荐
相关产品推荐

