Fortran Coder

查看: 24315|回复: 9
打印 上一主题 下一主题

[讨论] 关于Fortran的赋值

[复制链接]

69

帖子

7

主题

0

精华

专家

F 币
320 元
贡献
224 点
跳转到指定楼层
楼主
发表于 2014-2-25 10:30:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 jason388 于 2014-2-25 10:31 编辑

Fortran标准对赋值(variable=expr)运算定义了三步操作:
1. 计算表达式expr及variable中的所有表达式;
2. 如果expr运算结果的类型或类型参数与variable不同,则将其转化为与variable相同;
3. 按上面计算结果定义variable。
理解了上面的定义,下面的例子不言自明:

[Fortran] 纯文本查看 复制代码
program test_assignment
implicit none
integer :: a(10,10)=1,b(10,10)=2
integer :: v(10)=[2,1,4,6,2,10,7,9,8,1]
integer :: i,j,n=10
integer, allocatable :: c(:)
real(kind=8) :: x,y

x=3.141592653589793; y=3.141592653589793_8
print '(2(a,g0,x),/)',"x=",x,"y=",y

x=1/2+x/2; y=1.0_8/2+y/2;
print '(2(a,g0,x),/)',"x=",x,"y=",y

forall(i=2:n-1,j=2:n-1)
  a(i,j)=a(i,j-1)+a(i,j+1)+a(i-1,j)+a(i+1,j)
  b(i,j)=a(i,j)
end forall
print '(a/,10(i0,x))',"b=",(b(i,:),i=1,n)

forall(i=1:10)a(i,:)=i
print '(/a/,10(i0,x))',"a(:,1)=",a(:,1)

a(:, 1)=a(v(:),1)
print '(/a/,10(i0,x))',"a(:,1)=",a(:,1)

allocate(c(5))
c=3
c=v
print '(/a/,10(i0,x))',"c=",c
deallocate(c)
end program test_assignment


用gfortran编译,其计算结果为:
x=3.1415927410125732 y=3.1415926535897931

x=1.5707963705062866 y=2.0707963267948966

b=
2 2 2 2 2 2 2 2 2 2
2 4 4 4 4 4 4 4 4 2
2 4 4 4 4 4 4 4 4 2
2 4 4 4 4 4 4 4 4 2
2 4 4 4 4 4 4 4 4 2
2 4 4 4 4 4 4 4 4 2
2 4 4 4 4 4 4 4 4 2
2 4 4 4 4 4 4 4 4 2
2 4 4 4 4 4 4 4 4 2
2 2 2 2 2 2 2 2 2 2

a(:,1)=
1 2 3 4 5 6 7 8 9 10

a(:,1)=
2 1 4 6 2 10 7 9 8 1

c=
2 1 4 6 2 10 7 9 8 1


分享到:  微信微信
收藏收藏1 点赞点赞 点踩点踩

736

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
700 元
贡献
359 点

新人勋章爱心勋章水王勋章元老勋章热心勋章

沙发
发表于 2014-2-25 11:22:35 | 只看该作者
jason 的帖子非常好,不但说明了赋值中的类型精度问题,还说明了 forall 的一些用法。值得好好琢磨一下。

补充一些想法:
1.尽管语法允许赋值的时候variable和expr的类型或精度不同,但我依然建议不要这样。尽量保证两边类型精度一致。
2.如真的需要不一致的类型或精度,最好显式地加上转换函数,例如:
[Fortran] 纯文本查看 复制代码
integer :: i = 1.0
real :: r
r = real(i)


3.常量也有类型和精度,这一点要格外注意。如果代码中有大量的变量或常量需要指定精度,建议不要用 _8 这样的数字后缀。

[Fortran] 纯文本查看 复制代码
Implicit None
Integer , parameter :: I4  = SELECTED_INT_KIND( 8 )
Integer , parameter :: R8 = SELECTED_REAL_KIND( 6 , 70 )
Integer( Kind = I4 ) :: iVar1 , iVar2
Real( Kind = R8 ) :: rrVar1 , rrVar2
Real( Kind = R8 ) :: rrVar3 , rrVar4
rrVar1 = 1.0_R8


4. forall 虽然相当于循环,但不完全一样,除了在并行计算中的优势之外,还可以实现很多常规Do循环比较难处理的计算。但是使用它要格外小心。

jason 输出二维数组的语句很好,简单高效。

69

帖子

7

主题

0

精华

专家

F 币
320 元
贡献
224 点
板凳
 楼主| 发表于 2014-2-26 08:19:54 | 只看该作者
本帖最后由 jason388 于 2014-2-26 08:40 编辑
chuxf 发表于 2014-2-25 11:22
jason 的帖子非常好,不但说明了赋值中的类型精度问题,还说明了 forall 的一些用法。值得好好琢磨一下。

...

1. 对于有一定规模的程序确实不应用(kind=8)这种采用具体数字定义类型参数的形式,而应采用selected系列函数。
比如对于单精度和双精度的下列定义是不依赖于任何编译器和机器类型的:
[Fortran] 纯文本查看 复制代码
integer,parameter :: sgl=selected_real_kind(p=6)
integer,parameter :: dbl=selected_real_kind(p=13)
real(kind=sgl) :: pi1=3.14159_sgl
real(kind=dbl) :: pi2=3.14159265_dbl

2. forall和where结构本质上是赋值操作,这里以forall举例一是说明数组赋值的方法,二是强调forall的赋值性质。
3. 前两个例子是初学者非常容易忽略的地方,在较大规模程序中这样的问题一般还不容易发现,所以这里特别予以强调。
4. 严格说起来,字面常数(literal constant)最好都给出类型参数,避免因为编译器内部转换等原因而达不到本来的意图。

2033

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1641 元
贡献
709 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

地板
发表于 2014-2-26 09:58:20 | 只看该作者
感谢jason分享您的经验。

要让大伙养成这些好的习惯,恐怕还需要一个过程。

69

帖子

7

主题

0

精华

专家

F 币
320 元
贡献
224 点
5#
 楼主| 发表于 2014-3-1 09:19:47 | 只看该作者
fcode 发表于 2014-2-26 09:58
感谢jason分享您的经验。

要让大伙养成这些好的习惯,恐怕还需要一个过程。 ...

Fortran90一直到2008标准新增的功能使Fortran真正进化为一种功能强大的Formula Translation语言,真正对Fortran感兴趣的人确实需要好好地学习一下这些新增的功能并在新的程序中实践之,个人觉得用新标准写的代码相对其他语言(包括f77)更加简洁、容易理解且充满美感。

但遗憾的是大部分同学估计都是为了应付学业才接触Fortran代码而非对其真正感兴趣的,这也就是到现在还在用那些老掉牙的编译器以及讨论f77代码不断的原因吧。

2033

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1641 元
贡献
709 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

6#
发表于 2014-3-1 09:36:09 | 只看该作者
jason388 发表于 2014-3-1 09:19
Fortran90一直到2008标准新增的功能使Fortran真正进化为一种功能强大的Formula Translation语言,真正对F ...

jason 说得没错,对此我也表示很遗憾。

建立这个网站和论坛,一方面是QQ群有归档常见问题和讨论的需求,另一方面也是希望能培养网友们对新语法的习惯。

有一些朋友看到网站上的资源并不多,比中科大的那个Fortran资源页面少很多,会发送一些电子书给我,希望添加在网站上。但我依然坚持不把老掉牙的 F77 资料推荐给网友,而是尽量保证推荐的资源都是 F90+ 语法的。

新语法简洁,易于理解,且更科学,表达意思明确,可避免大量歧义。值得推荐,因此网站上的代码我都尽量修改为更好的风格再发出去。

目前正在教学栏目里做一个关于新语法的系列(目前还只有一篇),希望有时间的话多写一些。

如果jason有兴趣或者有整理好的关于新语法的文字,可以在线投稿或发送到我的邮箱 gao@fcode.cn

69

帖子

7

主题

0

精华

专家

F 币
320 元
贡献
224 点
7#
 楼主| 发表于 2014-3-1 09:53:14 | 只看该作者
fcode 发表于 2014-3-1 09:36
jason 说得没错,对此我也表示很遗憾。

建立这个网站和论坛,一方面是QQ群有归档常见问题和讨论的需求, ...

争取有时间时努力下。虽然用F95好多年了,但认真学习2003和2008标准也是最近才开始的。

2033

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1641 元
贡献
709 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

8#
发表于 2014-3-1 10:03:48 | 只看该作者
jason388 发表于 2014-3-1 09:53
争取有时间时努力下。虽然用F95好多年了,但认真学习2003和2008标准也是最近才开始的。 ...

那倒也不必刻意去写,不耽误其他工作学习生活的前提下。

1

帖子

0

主题

0

精华

新人

F 币
28 元
贡献
8 点
9#
发表于 2021-3-10 21:54:14 | 只看该作者
请问如果是运算过程中造成的精度损失要怎么解决呢?就比如这里的y,如果是中途计算出来的,然后用它进行另一个运算的时候,y就不是计算出来的y了。

213

帖子

2

主题

0

精华

宗师

F 币
2142 元
贡献
875 点

规矩勋章

10#
发表于 2021-3-12 00:15:24 | 只看该作者
forall语句在Fortran2018标准被认为“过时”,处于淘汰中。因为有了新的Do concurrent语句,使得Forall显得多余。“过时”的功能或语句在新的标准中或被移除,不推建使用。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-12-24 01:40

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表