昨天学习了一些简单的数组操作,包括数组声明、赋值,今天来学习一些对数组的整体操作:
1、统一赋值:
program Max
integer::a(5)
//!通过这一句,就可以把a数组的所有值全部赋值为5(没办法,为了代码有颜色,我只好把他们用c++注释符给注释掉了)
a=5
write(*,"(I1)")(a(i),i=1,5)
stop "over"
end
结果当然就是输出五个5咯:
其实这个stop“message”中的message是可以不用加的,但是吧,我觉得加上之后,在message里面随遍写点啥,后面兴许可以搞错误判断。
也可以这样子:
a=(/5,5,5,5,5/)
//!当然也是一样的效果,可以自己试一试
当然,数组运算有没有简单一些的办法嘞?答案是肯定的,比如说通过两个同维度的数组对另一个数组进行赋值:这里先设定两个同维度数组ArrayB,ArrayC,用他们对另外一个数组ArrayA进行赋值:
program Max
integer::ArrayB(4)
integer::ArrayC(4)
integer:: ArrayA(4)
ArrayB=3
ArrayC=4
!a=b+c
ArrayA=ArrayB+ArrayC
write(*,"(I3,I3,I3,I3)")(ArrayA(i),i=1,4)
stop "over"
end
program Max
integer::ArrayB(4)
integer::ArrayC(4)
integer:: ArrayA(4)
ArrayB=3
ArrayC=4
!a=b-c
ArrayA=ArrayB-ArrayC
write(*,"(I3,I3,I3,I3)")(ArrayA(i),i=1,4)
stop "over"
end
program Max
integer::ArrayB(4)
integer::ArrayC(4)
integer:: ArrayA(4)
ArrayB=3
ArrayC=4
!a=b*c
ArrayA=ArrayB*ArrayC
write(*,"(I3,I3,I3,I3)")(ArrayA(i),i=1,4)
stop "over"
end
program Max
integer::ArrayB(4)
integer::ArrayC(4)
integer:: ArrayA(4)
ArrayB=3
ArrayC=4
!a=b/c
ArrayA=ArrayB/ArrayC
write(*,"(I3,I3,I3,I3)")(ArrayA(i),i=1,4)
stop "over"
end
你甚至可以用一些fortran的内置函数来进行操作:
program Max
REAL::ArrayB(4)
real::ArrayC(4)
real:: ArrayA(4)
ArrayB=3
ArrayC=4
//!开方
ArrayA=sqrt(ArrayB*ArrayB+ArrayC*ArrayC)
write(*,"(F5.2,F5.2,F5.2,F5.2)")(ArrayA(i),i=1,4)
stop "over"
end
行了,基础可以之后,来试试对一个二维数组进行处理
program mat
INTEGER::matrixA(4,4)
integer::matrixB(4,4)
integer::matrixC(4,4)
matrixA=1
matrixB=3
matrixC=matrixA*matrixB
write(*,"(I2,I2,I2,I2/I2,I2,I2,I2/I2,I2,I2,I2/I2,I2,I2,I2)")((matrixC(i,j),i=1,4),j=1,4)
stop "over"
end
输出:
好了,对整个数组的操作在就没啥好说的了,现在进入到下一块内容,切片操作:
其实看了一些fortran对数组切片操作的语法之后,第一个感觉就是,怎么越看越像python里的切片操作,除了坐标选择是使用"()"以外,没有太大的区别,这可能也就是编程语言的更新和发展吧,去其糟粕,取其精华,好了不多说了,开始。
切片的目的在于对部分数组进行操作而不影响数组其他元素,显然,数组的下标操作就是极为重要的了,这里就不和上面一样,全贴代码了,我直接敲一些语句就好,如果有需要的话,可以直接复制,改成适用于你程序的参数就好:
//!最简单的操作:取部分数组:
array(3:5)=2
//!取出array(3),array(4),array(5)这三个,直接给赋值为2
array(3:)=2
//!array(3)之后的数都赋值为2(包括array(3))
array(3,9,2)=2
//!array(3),array(5),array(7),arrray(9)这几个数赋值为2,其实就是arrray(counter,upperbound,step)
array(1:10)=array(10:1:-1)
//!这个就是数组的倒转,python直接就是a=a[:-1],算是对Fortran的改进吧
array(:)=array_one(:,2)
//!这个的意思就是把array_one的第二列赋值给array
array(:,:)=array_two(:,:,x)
//!和前面的同理,就是把三维矩阵array_two的第x个矩阵赋值给array
注意:必须是同维度才能操作,如果你是一个3*3的数组,偏要给一个2*2的数组赋值,必须切片,否则就会报错,别问为什么,大一刚学c++时候的惨痛教训!!!
简单的来一个吧:
program main
implicit none
integer row,col
parameter(row=2)
parameter(col=2)
integer::a(2,2)
integer::b(4)
integer::c(2)
integer i,j
data ((a(i,j),i=1,2),j=1,2)/1,2,3,4/
b=(/5,6,7,8/)
write(*,*)a
write(*,*)a(:,1)
c=a(:,1)
write(*,*)c
c=a(2,:)
write(*,*)c(2:1:-1)
c=b(1:4:2)
write(*,*)c
stop "program over"
end
//!彭国伦Fortran90那本书的ex0709不对劲,他原先的程序是这样子的:
program main
implicit none
integer row,col
parameter(row=2)
parameter(col=2)
integer::a(2,2)=(/1,2,3,4/)
integer::b(4)=(/1,2,3,4/)
integer::c(2)
write(*,*)a
write(*,*)a(:,1)
c=a(:,1)
write(*,*)c
c=a(2,:)
write(*,*)c(2:1:-1)
c=b(1:4:2)
write(*,*)c
stop "program over"
end
//!就老是会出现一个报错:Incompatible ranks 2 and 1 in assignment at (1)
//!我查了好多,但因为Fortran很老的缘故,并没有查出所以然来,只是有人在里面说a是个可变数组巴拉巴拉。
//!就离谱,没办法我就按之自己的方法对a数组进行赋值,就是最上面的代码,哎,他就对了,emm...百思不得其解啊
展示一下输出一下效果:
和书上的一模一样:
,唉,怎么说呢,实现一种功能的方法特别多,就拿c++来说吧,你要想实现一个数组赋值,你可以直接赋值,你也可以for循环,while循环进行赋值,python就更多了,numpy提供了好多种赋值方法,只要给数组赋值成功,怎么办都行,不需要在这纠结于形式。
再一个,再说个事儿,Fortran有个很怪的地方,对一个变量的声明是不能放在给其他的赋值语句之后的,这样子就会报错,感觉很不人性化,给大家看个很简单的例子:
program main
implicit none
INTEGER::a
a=8
integer::b
write(*,*)a
stop "over"
end
哎,就离谱,可能后面的开发者实在是扛不住这么造(都写了几百行代码,忽然发现有个新功能要再声明几个新变量),所以后面c++,python等,不管是编译语言还是解释语言,都可以随时随地的去声明变量。
非常重要的两个数组命令:where和 forall:
where是一个通过逻辑判断来使用数组中的某些元素;
forall相当于用隐式循环来使用数组。
当然他们的用法是非常简单的,直接套用我下面的这个模板就ok,我就再不用代码段来展示运行成果了:
//!where;
where (!逻辑判断1)
//!对满足逻辑判断要求的数组元素进行操作
//!where是可以嵌套的,也可以用elsewhere来创造其他的操作判断:
elsewhere(!逻辑判断(在这里是可有可无的))
//!你甚至可以嵌套进行
where(!逻辑判断2)
...
end where
end where
//!forall
forall (triplet1,triplet2,triplet3,... mask(!mask就是逻辑判断))
//!其中tripleti 就是i=1:100,就是个隐含循环
end forall
看到forall,你有没有想到啥:for循环,老朋友了!!!
今天就到这里吧,明天讨论一下Fortran中数组的保存以及一个非常重要的工具:可变数组。