《FORTRAN速成篇》(四) 数组

(1) 数组的声明

(1.1) 一维数组的声明

datatype name(size)
datatype,dimension(size) :: name
datatype name
dimension name(size)

其中size只能为常数。

(1.2) 二维数组的声明

datatype name(size1,size2)
datatype,dimension(size1,size2) :: name
datatype name
dimension name(size1,size2)
  1. 一个二维数组的元素个数等于size1*size2。
  2. n维数组的声明可以类推,这里不再赘述。
  3. Fortran数组的索引值都是由1开始。但是也可以通过特别声明的方法来改变这个默认规则:
datatype name(start:end)

表示索引值从start开始。

(2) 数组内容设置

(2.1) 给数组元素赋初值

integer a(5)
data a/1,2,3,4,5/
!a(1)=1,a(2)=2,a(3)=3,a(4)=4,a(5)=5

integer a(5)
data a/5*3/
!a(1)=a(2)=a(3)=a(4)=a(5)=3

integer a(5)
integer i
data(a(i),i = 2,4) /2,3,4/
!隐式循环,相当于将a(2)=2,a(3)=3,a(4)=4,a(1)a(5)尚未设定。

!隐式循环的其他用法:
print*,(a(i),i = 2,4)
!显示a(2),a(3),a(4)
print*,(a(i),i = 2,6,2)
!显示a(2),a(4),a(6)
data( ( a(i,j),i = 1,2 ),j = 1,2 ) /1,2,3,4/
!里面括号的循环先执行,相当于a(1,1)=1,a(2,1)=2,a(1,2)=3,a(2,2)=4

!也可以省略掉data描述直接设置初值。
integer :: a(5) = (/1,2,3,4,5/)
integer :: a(5) = (/1,(2,i = 2,4),5/)
!a(1)=1,a(2)=a(3)=a(4)=2,a(5)=5
integer :: a(5) = (/(i,i = 1,5)/)
!a(1)=1,a(2)=2,a(3)=3,a(4)=4,a(5)=5

!Fortran有其他语言没有的、可以一次性直接把整个数组内容设置为同一个数值的功能:
integer :: a(5) = 5
!a(1)=1,a(2)=2,a(3)=3,a(4)=4,a(5)=5

下面来看一个输出矩阵的例子:

program main
    implicit none
    integer,parameter :: row = 2,col = 2
    integer m(row,col)
    integer r,c
    data( (m(r,c),r = 1,2),c = 1,2 ) /1,2,3,4/
    !m(1,1)=1,m(2,1)=2,m(1,2)=3,m(2,2)=4
    write(*,'(i3,i3,/,i3,i3)') ( (m(r,c),c = 1,2),r = 1,2 )
    !输出矩阵,斜杠表示换行。
end program main

(2.2) 对整个数组元素操作

a = 5
!把数组a的每个元素的值都设置为5

a = (/1,2,3/)
!a(1)=1,a(2)=2,a(3)=3
!等号右边的数字数目必须和数组a的大小一样。

a = b
!俩同维数组之间的赋值。

a = b +- c
!两个同维数组对位置相加减再赋给数组a

a = b */ c
!两个同维数组对位置相乘除再赋给数组a

a = sin(b)
!对b的每个元素取正弦值再赋给a,其中b必须是浮点型数据。

a = b > c
!同类型的数值数组b和c进行逻辑运算后将逻辑值赋给逻辑型数组a

(2.3) 对部分数组元素操作

a(3:5) = 5
!对a中第三个到第五个元素赋值为5

a(3:) = 5
!将a中第3到最后一个元素赋值为5

a(1:5:2) = 3
!a(1)=a(3)=a(5)=3

a(1:10) = a(10:1:-1)
!把a中的元素翻转。

a( : ) = b( : , 2 )
!把b第二列的元素赋给a

(2.4) where语句

where(数组1的逻辑表达式) 数组2 = 数组1
where(数组1的逻辑表达式)
    数组2 = 数组1
end where
where(数组1的逻辑表达式)
    数组2 = 数值1
elsewhere
    数组2 = 数值2
end where
where(数组1的逻辑表达式1)
    数组2 = 数值1
elsewhere(数组1的逻辑表达式2)
    数组2 = 数值2
    ...
elsewhere(数组1的逻辑表达式n-1)
    数组2 = 数值n-1
elsewhere
	数组2 = 数值n
end where

假设年所得30000以下所得税率为10%,30000-50000之间为12%,50000以上为15%。记录10个人的所得税金额。

program main
    implicit none
    integer :: i
    real :: income(10) = (/25000,30000,50000,40000,&
                &35000,60000,27000,45000,20000,70000/)
    real :: tax(10)
    where(income < 30000.0)
        tax = income * 0.10
    elsewhere(income < 50000.0)
        tax = income * 0.12
    elsewhere
        tax = income * 0.15
    end where
    write(*,'(10(f8.1,1x))') tax
    !10表示有10个数,1x表示每个数之间空一格。
end program main

(2.5) forall语句

forall语句的本质作用是通过循环对数组中的元素进行修改或者调用。 下面直接看一个例子来体会该语句的用法。

使用forall语句把矩阵的上半部设置为1,对角线设置为2,下半部设置为3.

program main
    implicit none
    integer i,j
    integer,parameter :: size = 5
    integer :: a(size,size)
    
    forall(i = 1:size,j = 1:size,i > j)
        a(i,j) = 1
    end forall
    !上半部分。
    
    forall(i = 1:size,j = 1:size,i == j) a(i,j) = 2
    !对角线。
    forall(i =1:size,j = 1:size,i < j) a(i,j) = 3
    !下半部分。
    
    write(*,'(5(5(i5),/))') a
end program main

可以在forall中使用where,但不可以在where中使用forall

(3) 数组的保存规则

  1. 多维数组的元素,在内存中的连续模块中排列是以一种称为“column major”的方法来排列的。
  2. 数组存放在内存中,会先放入column中每个row的元素,第1个column放完后再放第2个column。
  3. 计算机在读取大笔数据时,如果每一笔数据都位于邻近的内存位置中,执行效率会更高。这主要是使用高速缓存cache的缘故,高速缓存的访问速度比主存储器快上好几倍,cpu需要数据时,会先检验这个数据有没有存放在cache里,没有在cache中才会到比较慢的主存储器中拿数据。而向主存储器拿数据时,除了会拿回所需要的数据外,通常还会顺便把这笔数据的邻近几笔数据也拿回来放在cache里,所以下一笔数据如果距离不是很远,通常就会顺便被拿到cache中,这样可以加快下一个命令的执行速度。

遍历一个二维数组。

!欠妥方式
do i = 1,n
    do j = 1,m
        a(j,i) = ...
    end do
end do
!恰当方式
do i = 1,n
    do j = 1,m
        a(i,j) = ...
    end do
end do

(4) 可变大小的数组

在某些情况下,要等到程序运行之后才会知道所需要使用的数组的大小。这时候就要用到动态分配内存。先来看一个例子:

program main
    implicit none
    integer :: i,students
    integer,allocatable :: a(:)
    !声明一个可变大小的数组a
    print*,'Please input the number of students:'
    read*,students
    allocate(a(students))
    !配置内存空间。
    do i = 1,students
        write(*,"('number',i3)") i
        read*,a(i)
    end do
    print*,a
    deallocate(a) !释放内存。
end program main

此外也可以用allocate声明和配置多维数组:

integer,allocatable :: a2(:,:)
integer,allocatable :: a3(:,:,:)
allocate(a2(5,5))
allocate(a3(5,5,5))

也可以设定数组索引的初始值:

integer,allocatable :: a1(:)
integer,allocatable :: a2(:,:)
allocate(a1(-5:5))
allocate(a2(-3:3,-3:3))

检验是否已经配置内存:

if(.not. allocated(a)) then
    allocate(a(5))
end if

参考文献:

  1. 《工程分析程序设计》.陈斌、周屈兰.西安交通大学出版社.

本文作者:
  Aiden Lee
特别声明:
  文章仅供学习参考,转载请注明出处,严禁盗用!

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页