zoukankan      html  css  js  c++  java
  • Fortran学习笔记5(数组Array)


    数组的声明方式

    数组是组织数据的一种方式。用来记录类型、性质相同的长串数据。不论定义多少维的数组,数据在内存中都是线状储存的。

    一维数组

    datatype   name(size)
    ! datatype 是数组的类型,有整型、实型、复型、逻辑型、自定义型
    ! name 数组的名字
    ! size 数组的大小
    
    integer a(10)                  ! 第一种定义方法
    integer,dimension(10)::a       !第二种定义方法
    integer a                      !第三种定义方法,该方法先声明类型,在定义大小
    dimension a(10)

    二维数组

    integer a(2,3)              ! 最简单的方法
    integer,dimension(2,3)::a   ! 第二种方法
    integer a                   ! 第三种方法
    dimension a(10,10)

    多维数组

    Fortran最多可声明高达7维数组。

    integer a(2,2,2,...,2)
    integer,dimension(2,2,2,...,2)::a
    integer a
    dimension a(2,2,2,...,2)

    数组索引值的改变

    Fortran中数组的索引值可以改变,只需要在声明数组的时候注明特别赋值数组的坐标值范围。如:

    integer a(0:5)      ! 该数组的索引值为0,1,2,3,4,5
    integer a(-2:2,0:4,-5:-1)  ! 这也是可以的,有木有觉得很强大?

    自定义类型的数组定义

    直接给出例子:

    Type::person
       real::height,weight
       character(len=80)::name
     End type
    
     Type(person)::a(10)
     ...
     ...
     a(2)%height=180.0    !在变量后面加上%来使用变量中的元素
     a(2)%weight=70

    对数组内容的设置

    数组内容的设置,既可以的那个元素设置,也可以对整个数组操作,还可以对数组中的部分判断操作。

    利用“隐含式”循环设置数组初值

    integer a(5)
    data a /1,2,3,4,5/
    integer a(5)
    data a/5*3/   ! 5*3表示53.a(1)=3,a(2)=3,a(3)=3,a(4)=3,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)没有设定
    integer a(2,2)
    data ((a(i,j),j=1,2),i=1,2)=/1,2,3,4/
    integer::a(5)=(/1,2,3,4,5/)    !括号和除号之间不能有空格
    integer::i
    integer::a(5)=(/1,(2,I=2,4),5/) !a(1)=1,a(2)=2,a(3)=2,a(4)=2,a(5)=5
    integer::i
    integer::a(5)=(/(i,i=1,5)/)

    对整个数组操作

    这个功能是Fortran90添加的,在Fortran77中不适用。

    integer::a(5)
    a=5   ! 最后得到a的五个元素都等于5
    integer::a(5,5),b(5,5),c(5,5)
    c=a+b       !  相当于c(i,j)=a(i,j)+b(i,j)
    c=a-b       !  相当于c(i,j)=a(i,j)-b(i,j)
    c=a*b       !  相当于c(i,j)=a(i,j)*b(i,j)
    c=a/b       !  相当于c(i,j)=a(i,j)/b(i,j)
    a=sin(b)    !  相当于a(i,j)=sin(b(i,j))
    c=a>b       !  当a(i,j)>b(i,j)时,c(i,j)=.true.,否则c(i,j)=.Flase.

    对部分数组的操作

    除了一次对整个数组进行操作之外,Fortran90还提供一次只挑出部分数组来操作的功能。取出部分数组的语法看起来有点像隐含式循环。

    a(3:5)=5             !a(3)=5,a(4)=5,a(5)=5
    a(3:)=5              !a(3)=5,a(4)=5,...,a(n)=5
    a(3:5)=/3,4,5/       !a(3)=3,a(4)=4,a(5)=5
    a(13)=b(2:4)       !a(1)=b(2),a(2)=b(3),a(3)=b(4)
    a(1:5:2)=3           !a(1)=3,a(3)=3,a(5)=3,后面的2表示循环增量
    a(1:10)=a(10:1:-1)   ! 将a的值翻转
    a(:)=b(:,2)          ! a的元素与b的2列的元素对应
    a(:,:)=b(:,1,:)a的元素与b的1,3维元素对应相等
    where函数

    where命令经过逻辑判断来设定数组的一部分元素。where可以嵌套,也可以多重判断。where还可以命名,命名的where块要在结束时加上名字,以表明结束的是哪一个where。并且,where只用来数组赋值,不能用来干其他事。并且同一个where块中涉及运算的数组大小相同。

    program main
        implicit none
        integer ::i
        real::a(10)=(/ (i,i=1,10) /)
        real::b(10)
        where (a<3)
            b=1
            elsewhere(a<5)
                b=2
                elsewhere(a<8)
                    b=3
                    elsewhere
                        b=4
        end where
        write(*,100)a
        write(*,101)b
    100  format(T5,'Matrix A is : ',/,5(F6.2),' ')
    101  format(T5,'Matrix B is : ',/,5(F6.2),' ')
    end program

    以下摘自彭国伦《Fortran95程序设计》

    name: where(a<5)  ! where模块可以取名字
    b=a
    end where name    ! 有取名字的where结束时也要赋值名字
    
    where(a<5)        ! where可以嵌套
       where(a/=2)
          b=3
       elsewhere
          b=1
       end where
    else where
       b=0
    end where
    Forall函数

    Forall的语法为:

    Forall(triple1[,triple2[,triple3...]],mask)
    ......
    end forall     ! mask是条件限制,满足该条件的数组元素进行Forall操作

    例如:

    integer::a(20,5)
    integer::i,j
    forall(i=2:20:3,j=1:5)
        a(i,j)=i+j
    end forall

    Forall描述的程序模块如果只有一行代码,可以省略end Forall,把程序终结跟在Forall后面,写在同一行。下面给出几个例子。

    integer::i,j
    integer::a(20,10)
    ......
    ......
    forall (i=1:5,j=2:8:2,a(i,j)<10)  ! 只处理a中小于10的元素
         a(i,j)=1
    end forall
    
    forall(i=2:13:3,j=1:5,((i>j).AND.a(i,j)>0)) a(i,j)=i**2+j**2

    Forall可以写成多层嵌套,它里面也只能出现跟设置数组数值相关的命令程序,还可以在Forall中使用where,但是,不能再where中使用Forall

    下面给出一个例子,要求生成一个20*20的矩阵。该矩阵是一个带状矩阵。主对角元为8,上次一级为6,再次一级为0,再次一级为4,如此生成。下对角元和上对角元相同,只是把数字换成7,5,3,1。

    program main
        implicit none
        integer::i,j,k
        integer::a(20,20)
        !数组置零
        a(:,:)=0
        Do k=-8,8,2
            if(k<0)then
                forall(i=1:20,j=1:20,i==j+k)     a(i,j)=k+9     
    !请注意,Fortran在循环的过程中总是先循环最内层,所以这里i代表列,j代表行。不能搞反了。
            end if
            if(k>=0)then
                forall(i=1:20,j=1:20,i==j+k)     a(i,j)=-k+8
            end if
        End Do
        write(*,100)a
    
    100      format(T5,'矩阵为:',/,20(I2),'  ')
    
    end program

    数组的保存规则

    一个数组不论它是什么形状,它的元素在内存中的分布都是连续的。一维数组按顺序排列,多维数组在内存中按照“Column Major”的方法来排列。所谓“Column Major”总结起来就是先列后行,先低维在高维。在循环的过程中,要按照低维循环在内,高维循环在外的方式。

    integer::a(2,2,2)
    ! 排列顺序为:
    a(1,1,1)-a(2,1,1)-a(1,2,1)-a(2,2,1)-a(1,1,2)-a(2,1,2)-a(1,2,2)-a(2,2,2)

    假设声明了一个n维数组A(D1,D2,…,Dn),设Sn=D1D2Dn,则A(d1,d2,d3,...,dn)在第1+(d11)+(d21)S1++(dn1)Sn1个位置。

    如果声明的n维数组有设定每一维的起始值A(S1:E1,S2,E2,,Sn:En),设Mn=(E1S1+1)(E2S2=1)(EnSn+1),则A(d1,d2,d3,.dn)在第1+(d1S1)+(d2S2)M1++(dnSn)Mn1个位置。


    可变大小的数组

    Fortran77中没有可变大小的数组。Fortran90添加了可变大小的数组。使用可变大小的数组时要经过两个步骤。第一步是声明,在声明的时候要加上ALLOCATEBLE 。数组的大小用冒号代表。第二步是确定数组的大小。

    allocate命令从内存中获得一定空间,deallocate释放掉该空间。

    program main
        implicit none
        integer::size=0,error=0
        integer,parameter::onemb=1024*1024
        character,allocatable::a(:)
    
        do while(.true.)
            size=size+onemb
            allocate(a(size),stat=error)
            if(error/=0)exit
            write(*,"('Allocate ',I10,' bytes')")size
            write(*,"(F10.2,' Mb used')")real(size)/real(onemb)
            deallocate(a)
        end do
        stop
    end program

    allocated用来检查一个可变大小的矩阵是否已经配置了内存,它会返回一个逻辑值。

    if(.not. allocated(a))then
        allocate(a(5))
    end if
  • 相关阅读:
    ubuntu12.04 LTS 安装vmware 错误解决方法
    Linux 下的Bluetooth 架构 分类: Android驱动 20120316 11:07 492人阅读 评论(0) 收藏 举报 实战Linux Bluetooth编程(一) 协议栈概述
    通过DEFINE 生存config.h 配置
    Git的初次使用 ; Git常用命令查询 ; Git push ; Git pull 20111216 17:32 在介绍安装和简单使用前,先看一下百度百科中的简介吧: ———————————
    Android BCM4330 蓝牙BT驱动调试记录
    Linux的cpufreq(动态变频)技术
    高通平台android开发总结
    ssh 客户端配置文件
    Jprofile使用随笔_1_安装与监控linux
    服务器cpu占用100%,如何排查(java进程&sql)
  • 原文地址:https://www.cnblogs.com/baowee/p/9556829.html
Copyright © 2011-2022 走看看