利用Fortran算法实现过程中,会使用大量动态数组,在动态数组append的时候,会遇到扩充数组长度的问题,近期在网上看到一种之前没见过的动态数组扩充方法,并对其进行测试,这里将测试情况和另外一种常用的动态数组扩充方法进行总结。
数组扩充方法一
测试示例
program test_4
integer,allocatable :: iv1(:)
real(8),allocatable :: iV2(:)
complex(8),allocatable :: iV3(:)
logical,allocatable :: iv4(:)
character(len=3),allocatable :: iv5(:)
integer :: i
integer :: num1
real(8) :: num2
complex(8) :: num3
logical :: num4
character(len = 3) :: num5
! integer
iv1 = [integer ::] !< an empty array, empty array constructor
do i = 1,4
num1 = i
iv1 = [iv1,num1] !< append array
enddo
print *,"interer = ",(iv1(i),i=1,4)
! real(8)
iv2 = [real(8) ::]
do i = 1,4
num2 = real(i,8)
iv2 = [iv2,num2]
enddo
print *,"real(8) = ",(iv2(i),i=1,4)
!
iv3 = [complex(8) ::]
do i = 1,4
num3 = cmplx(i,1E-2)
iv3 = [iv3, num3]
enddo
print *,"complex = ",(iv3(i),i=1,4)
! logical
iv4 = [logical ::]
do i = 1,4
num4 = (mod(i,2)==0)
iv4 = [iv4, num4]
enddo
print *,"logical = ",(iv4(i),i=1,4)
! character(3)
iv5 = [character(3) ::]
do i = 1,5
num5 = "aaa"
iv5 = [iv5, num5]
enddo
print *,"character(3) = ",(iv5(i),i=1,4)
end program
运行结果
interer = 1 2 3 4
real(8) = 1.00 2.00 3.000 4.00
complex =
(1.0,9.999999776482582E-003)
(2.0,9.999999776482582E-003)
(3.0,9.999999776482582E-003)
(4.0,9.999999776482582E-003)
logical = F T F T
logical = aaa aaa aaa aaa aaa
上边是F90 常见数据类型动态数组扩充的示例,并没有出现allocate等关键字,Console下可以正常运行,说明基础数据类型都可以用上边方法进行数组扩充;从示例可以看到最关键的两句是:(以integer为例子)
! integer
iv1 = [integer ::] !< an empty array, empty array constructor
iv1 = [iv1,num1] !< append array
之前没用过这样的扩充方法,所以不知道其语法版本,也没查到,为了进一步理解该方法的适用性,又做了两个测试,仅调整了数据类型,测试1整形二维数组;测试二 Type类型;
(1)测试1 - 二维数组
! 示例
program Test_1
integer,allocatable :: iv1(:,:)
integer :: i,j
integer :: num1
! integer
iv1 = [integer ::] !< an empty array, empty array constructor
do i = 1,4
do j = 1,3
num1 = i*j
iv1 = [iv1,num1] !< append array
enddo
enddo
do j = 1,3
print *,"interer = ",(iv1(i),i=1,4)
enddo
end program
测试1编译报错,显示数组维度不一致,应该和 iv1 = [inte] 有关,暂时不知道怎么改,有理解的可以交流一下;
(2)测试2 – type
program test_3
type :: Vec_type
real(8) :: x
real(8) :: y
real(8) :: z
end type
type(Vec_type),allocatable :: iV(:)
integer :: i
type(Vec_type) :: v1
iv = [Vec_type ::] !< an empty array, empty array constructor
do i = 1,4
v1.x = 0.d0
v1.y = 0.d0
v1.z = 0.d0
iv = [iv,v1] !< append array
enddo
print *,iv
end program
测试二同样编译报错,错误显示 Compilation Aborted (code 1) 这个错误类型还不能确定具体问题,我想应该和测试一的问题是一样的。
暂时综上,该扩充方法对基础数据类型一维数组扩充是比较容易的,但其有很大的适用局限,除基础类型一维数组外其他类型均无法使用。
数组扩充方法2
该方法适用性强,逻辑简单,下面以integer数组的扩充为例,写了个Subroutine,其他类型(Type、Pointer)的动态数组扩充都可以根据该方法简单修改实现:
!!整形数组扩充2倍
subroutine Array_Extend(array)
implicit none
integer,allocatable :: array(:) ! 要对array进行扩充2倍
integer,allocatable :: array2(:)
integer :: size1
if(allocated(array) == .false.)return ! 数组未分配,不用扩充
size1 = size(array)
allocate(array2(2*size1)) ! 临时数组,接收原始数组数据
! allocate(array2(size1+1) ! 每次扩充1个长度
array2(1:size1) = array(1:size1)
call move_alloc(array2,array) ! 临时数组释放,并将分配的空间赋给array
end subroutine
小结
Fortran动态数组扩充总结两个方法,如果还有更好的方法可以分享一下思路呦。