找回密码
 注册
查看: 4984|回复: 10

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

[复制链接]
发表于 2005-3-18 22:04:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
深度:Fortran闲谈
1.1 始于计算,终于计算
在荒莽的历史尽头,我们常常听说人类之所以能够凭借虚弱的身躯,一次又一次地打退其他凶猛动物的猖狂进攻,而终于成就为今日当之无愧的“万兽之王”,这个原因有很多种解释,比如说是劳动,说是手,说是大脑,莫衷一是,各有各的理论和证据,确实是个很难取得定论的问题,因此我想提出一种新的解释,大概是不会遭到立刻的覆灭性打击。
人类的进化始于计算,我相信。
在有关非洲黑猩猩的纪录片里面,可以看到黑猩猩也会用手使用工具,一个黑猩猩家庭为了生活也勤于劳动,一个黑猩猩群落社会里面的形形色色的政治行为,显示它们的大脑也不是很闲,但有一次我看到黑猩猩们抢香蕉时,总是把自己已经抢到手的香蕉给弄丢了而无知觉,突然觉得它们最缺乏的也许是算数的能力。
所以我想,人类的起源一定跟计算有莫大的关系。当然这些都是戏说而已,不过如果说人类的科学是从计算开始的,应该是不会有太大的争议的。
也许有人说人类的科学活动应该是起源于观察,但从动物行为学的角度来看,观察这种行为是很难界定的,而计算则是非常好界定的行为,因为最原始的计算行为显然应该就是数数。
可以想像,当人类开始意识到自我在这个世界的孤独存在时,对于日月星辰和风雨雷电的无常和力量该是多么地恐惧啊!而人类把自己从这种恐惧当中解救出来的第一个方法应该就是算数。
算数导致了人类最早的科学活动,即天文学和几何学。人们从对日月星辰的计数当中发现了天体的运行是有常的,而不是什么不可琢磨的妖魔鬼怪在主宰;从对土地与山河的度量中建立了明确的几何概念,从而对自己所生活的世界开始了真正的理解。而这种理解活动一旦开始,就无法停止了,演变至今,就构成了我们人类最值得自豪的成就-科学。
科学的历史表明了它的基础,就是计算。如果我们只是一味地观察,我们会纪录下来大量的经验,然而却无法理解这些经验的含义,更进一步,对于经验有了总结归纳之后,哪怕是进行计算的确切程度不同,也会导致不同的对于自然的理解。
一个很著名的例子,就是太阳系行星的运动的问题。对于古人来说,所谓行星的意思就是那些星星是相对于恒星在明显地运动,在漫天的相互位置不变的恒星的对比之下,很少的这种匆匆行者是非常引人注目的。于是很早开始人们就纪录这些行星的运行轨道。在古希腊时代,最有名的关于这些行星运动的研究是托勒密完成的,他对有关行星的纪录数据进行了计算,得到了一个极其“圆满”的行星运动模型,即以地球为宇宙中心,行星围绕地球做严格圆周运动。现在看来,他的观测数据肯定不会是很精确,而他的计算也不会很准确,一直到开普勒,在获得了非常精确的行星轨道运行的数据的基础上,进行了大量的计算,最终得到了革命性的开普勒三定律。接下来牛顿出场了,他更是一个计算天才,正是通过计算,从开普勒三定律获得了他的最伟大的发现,万有引力定律。
然后还是通过计算,我们现在可以运用牛顿万有引力公式的计算而把脚印留到月球的寂寞沙尘上。
还有一个非常独特的例子,就是中国的古代科学和技术,更是强烈地依赖计算。相比于古希腊,中国的古代数学几乎完全是以计算为中心的,翻开中国的古代数学书,一个鲜明的特点就是几乎完全是针对问题的数学计算方面的内容,而很少有古希腊传统的公理,定理与证明。
实际上,古代中国在技术上一直领先于世界,很难说跟这种重视计算的风格没有关系。其中最有名的例子就是祖冲之关于圆周率的计算,而我们现在都很清楚,祖冲之的计算不仅是为圆周率提供了一个远比西方要精确的具体数值,更重要的是提供了一种非常通用的计算方法,即一种近似积分计算,而这种计算方法对于古代中国的技术进步的重要作用,正是一个表明计算的重要性的典范。
如果说计算在科学的早期发展中扮演了关键的作用,那么我们还是可以说计算仍然在现代科学技术扮演着关键的角色。
固然现代的科学技术领域广阔而渊深,然而哪里没有计算的身影呢?甚至在某些科学哲学家的看法里面,能否进行计算是衡量一个理论是否已经成为科学的一个部门的标准。也许这种说法不免偏激,但是计算对于科学与技术的意义,确实是一个深刻的问题。我们不妨考察一下物理学里面计算所占据的地位,也许有助于更深地理解这个问题。
几乎是一直到十九世纪,物理学还是以实验为主要内容,进入二十世纪之后,一场物理学革命飞快地竖立了理论物理学的丰碑,足以与传统的实验物理学分庭抗礼。而这种局面在二战时期就开始改变,二战后在实验物理与理论物理之外,计算物理鼎足而立,导致这种变局的最关键的因素就是电子计算机的发明。
在计算机没有发明之前,人们不得不采取各种方式来回避过于庞大的计算问题,而大量的关键问题,又非得进行庞大的计算不可,以物理学为例,一旦我们透彻地解决了线性问题之后,接踵而来的就是远比线性现象更为广泛的非线性现象,对于非线性问题,我们已经掌握的解析方法极其贫乏,这就逼迫我们走上直接计算之路。
而除了非线性问题之外,物理学乃至整个自然科学看待世界的方式都是原子式的,即我们总是可以把一个现象理解为它的组成成分的相互作用的结果,于是我们就有了分子,原子等基本的科学观念,这种做法一直都是充满胜利的,然而这种胜利也是伴随着沉重代价的,即当我们重新面对复杂现象时,不得不从它的组成成分开始考虑,这就是统计物理学的基本思想,显然这种做法给我们带来了繁重的计算任务,因为迄今为止,我们人类对于一个包含超过了3个的,具有相互作用的成员的系统的精确解析求解,已经是有点一筹莫展了,更何况常见的那些动辄包含了成千上万成员的系统呢?因此在很大一部分情况下,我们唯一的选择,就是直接的计算。
因此我们可以说,计算确实是科学的基石之一。至于我们所生活的这个几乎完全由科学技术所塑造的世界,哪里没有计算的身影呢?
如果说计算帮助我们理解了自然,进一步我们还可以说计算创造了我们的生活。任何一个科学上的对于自然的新的理解,要转变为为人所用的技术时,基本的途径就是计算。道理很显然,当我们要制造一种自然界从未出现过的物品时,我们需要的是具体的制造数据,而不能只是一堆公式,那么数据从哪里来呢?当然只能从对公式的计算得来。因此我们可以把计算理解为理论的实现途径。即理论无论是要反映真实世界,还是要体现到我们的实际物品上,它都需要通过一条叫计算的路,理论武装了我们的大脑,而计算则创造了我们的世界。

所以我们可以说,人类的历史,最早是始于计算,而这个历史的实现的最前沿,则仍然是终于计算。
1.2描述计算的语言
长久以来,人类的计算都是依靠自己来完成的,但如果仔细考虑一下,就会发现计算的实质是把一个经过清楚的分析,明确了求解的方法的问题,分解为明确,可行,而有限的步骤,显然这种工作本质上是机械性的,如果把已经得到求解方法的问题还交给人脑来计算,显然有浪费人力之嫌;从另外一个方面来讲,往往一个需要专门加以计算的问题,也是一个需要进行庞大的计算的问题,庞大到人力已经难以胜任的程度。因此这两个方面都要求人类发明能够进行计算的机器,这就直接导致了计算机的发明。
今天当我们面临需要计算的问题时,对付问题的就不再只是一个大脑,而是一个大脑加上一台机器。所以接下来的问题就是如何让大脑与计算机协同工作,使得大脑能够专门用来寻求问题的算法,而计算机能够被用来计算解。
这种协同工作的第一个要求就是人需要能够把自己对于问题的计算过程的理解表示为机器的机械运动。首先人对于问题及其求解的理解是可以非常清晰地依靠数学语言来加以描述说明的。然后我们再看机器那一端。所谓计算机就是能够自动执行一系列机器动作的机器,对于那些机器动作,我们可以把它们和基本的计算操作对应起来,这就使得有可能把计算问题的能行的计算步骤分解为有限的机器操作,这里剩下的问题就是一方面是我们熟知的描述问题求解的数学语言,另一方面就是描述机器操作的语言,这两个方面的语言如何对应的问题。
下面我们讨论一个非常简单的例子,用来说明这里面的语言翻译问题。一个一元二次方程的求解是一个很简单的数学问题。设方程的形式为:
y=ax**2+b+c
那么方程的解的一般公式为:y1= () , y2= ().
注意我们现在的目的是计算,而不是求解析解,因此得到这个公式不是问题的结束,而是问题的开始,即运用这个公式,在a,b,c都有具体取值的情况下,求出具体的数值解。因为如果该方程描述的是一个抛体运动,那么我们需要知道的当然是解的数值,以便我们了解和控制该抛体运动。
所以我们还需要进一步把这个数学表述转述为一个具体的求值过程的描述如下:
(1)获得a,b,c的具体取值;
(2)根据a,b,c的具体取值计算的值;
(3)如果大于0,那么分别计算上面的两个公式的数值,得到两个不同的实数根;
(4)如果=0,那么计算公式,得到的y的值就是方程的两个相同的根;
(5)如果小于0,那么分别计算
上面的两个公式的数值,得到两个不同的复数根。
这样得到的上面的5个计算步骤描述,才是希望计算机所执行的计算过程的一个大概描述。当然这个描述是基于我们已经获得的对于一元二次方程的求解问题的数学上的彻底了解。
那么描述计算机的操作的语言是什么样的形式呢?
我们知道所谓计算机的工作在本质上是运行一些基本的机械电子操作,固然我们可以把那些操作根据运算法则而定义为相应的运算,例如一个开关电路的信号叠加,可以适当地定义为二进制数值的加法,但显然不可能期望依靠这种物理现象能够直接地表达更加复杂的计算,例如上面公式里面的开平方。幸好我们依靠数学,可以做到把任何复杂的计算分解或近似分解为极少数简单计算的叠加与组合。因此最终我们已经至少在理论上可以期望使用计算机来完成那些具有明确求解过程的计算任务。
然而问题是当我们需要向计算机提交一个数值计算任务时,如果总是要求我们首先把计算任务的描述按照计算机所能够理解和执行的程度来进行的话,无疑会使得向计算机提交计算任务成为一件极其麻烦的事情,本来我们利用计算机的目的是为了减轻自己的机械劳动工作量,如果向计算机提交问题是如此麻烦的话,显然不符合我们发明计算机的初衷。
因此进入二十世纪五十年代后,提出了计算机高级语言的概念,所谓高级语言,就是非常接近我们平常对于数学问题的描述的语言,而所谓给出计算机高级语言,实质上并不是说计算机能够直接理解高级语言了,而是把高级语言到计算机内部的机器语言的翻译工作本身交给计算机来完成,因为这种翻译工作在规范了高级语言之后,是计算机自身就完全可以做到的,当然这个翻译任务本身又是一个需要我们首先明确给出一般解答的计算问题。
世界上第一个诞生的计算机高级语言就是我们在这本书里要给出的FORTRAN。
FORTRAN最早是IBM公司在1957给出的,专门用于向IBM自己生产的704计算机提交表述计算问题的。一个计算问题的求解过程如果使用了计算机语言来表述,就称为一个程序,FORTRAN正是这样一种专门用来写程序的语言。
由于IBM的709计算机的成功,同时也使得FORTRAN获得了广泛的传播,这时FORTRAN的语言本性开始在另外一个方面显示了出来,即语言的生命就在于它的传播。于是大多数其它计算机制造商也纷纷使得他们的产品能够输入和理解FORTRAN语言。
FORTRAN语言从它的名称来源就可以知道是一种与某些特定机器进行通讯的语言工具。即FORTRAN语句可以通过特定的机器上配置的编译程序而翻译成机器语言,因此早期的FORTRAN语言具有强烈的与机器系统相关的一些特征,它们反映了那些特定机器的某些特点,显然如果考虑到高级语言的本质是要用来描述计算过程,即所谓算法语言,那么这些与机器相关的特征是没有意义的,而FORTRAN不断更新版本所带来的进步,也就包含了不断舍弃这种特征的目的在内。
FORTRAN的这种历史痕迹的一个例子就是把语言用那些特定机器所能接受的字符序列(亦就是IBM公司用来向计算机输入程序的卡片穿孔设备的48个字符)来定义.而它的那种卡片输入方式决定了很多的程序书写格式。例如通常把语言中的一个语句写在一个记录上,也就对应着穿孔的一张卡片;各个语句按顺序读入,对应着卡片的顺序读入;卡片的格式是固定的,构成后来所谓的固定源码形式。
这就是最初提出计算机高级语言时我们所拥有的第一种高级语言的状况。
不久降生的另外一种高级语言是ALGOL,这个名称就是算法语言的简称,因此可以预料到这种语言具有与FORTRAN非常不同的面貌,因为这种语言在设计初始,就不是计算机制造公司为某种特定机器设计的,而是纯粹面向描述计算过程的,也就是所谓面向算法描述的。
ALGOL最早是在1958年由德意志联邦共和国应用数学与力学协会提出的。ALGOL的设计目标显然比FORTRAN要来得高远,它希望不仅能够用于人对机器转述计算过程,也希望能够直接用于人与人之间的对于算法的描述。
为了实现这个通用的目的,ALGOL的字符不是针对任一具体机器定义的,因此它不反映任何一台特定机器的特性。实际上ALGOL所使用的字符与词汇完全是独立定义的。除此之外ALGOL还具有许多更加独特的性质。
不过语言终久摆脱不了它的市场属性,由于FORTRAN更加具有市场侵占能力,最终FORTRAN至今还是主流的科学计算编程语言,而ALGOL语言则不幸成为了任人凭吊的古董。
1.3为什么选择FORTRAN
到底选择什么样的语言,本身是一类非常具有争议性的问题。曾几何时,在科学计算领域,就沸沸腾腾地讨论过最好使用什么样的语言。也许我们可以说这是一个见仁见智的问题,因为我们作为语言的使用者,总是拣自己已经很熟悉的语言,当然总是自己能够很好驾驭的语言是最好的。但是具体地针对科学计算来说,由于科学计算问题具有自身的独特的价值标准,在这个价值标准之下,各种不同的语言还是可以进行客观比较的。
首先我们得把自己面临的任务界定清楚,也就是什么是科学计算问题?
所谓科学计算问题大体上包括如下三个涵义:
●问题本身以及问题的解答都能够使用数学语言予以精确描述;
●如果要使用通常的数学方法来给出我们所需要的数值答案,会很麻烦或者根本无法给出;
●问题以一定的科学与技术知识作为背景。
我们会看到正是科学计算问题的这种内涵决定了它在选择计算语言时所具有的价值标准。
首先,一个科学计算问题总是要以一个数学计算问题的形式出现,因此描述科学计算问题的语言应该能够自然地描述数学问题,即要求编程语言和数学语言在表达方式上具有比较直接自然的对应关系。
然后一个科学计算问题之所以需要使用计算机,那肯定是因为这个问题具有一定的计算量,那么程序的运行效率往往是选择语言时最重要的考量因素。
正是在这两点上,FORTRAN是现在众多语言当中的绝对胜出者。在描述数学语言的自然性方面,FORTRAN可以说比现在还“活”着的任何语言都强。当然在历史上曾经出现过象ALGOL那样的相当数学化的语言,可惜的是它缺乏市场生存能力,所以就只剩下FORTRAN独美于今了。FORTRAN擅长描述数学计算,这点应该是几乎没有什么争议的。也正是由于这个缘故,FORTRAN的易学是公认的。任何一个科技专业人员,只要对于一个具体问题的数学求解过程有明晰的概念,要把这个求解过程翻译为FORTRAN语言是非常轻松的。
至于执行速度方面,则常常有些似是而非的说法误导初学者。最典型的一个错误观念就是“C代码的执行速度最快”。这个说法来源于C语言的特殊性,因为C语言更多的是一种系统编程语言,对硬件的控制能力很强,在高级语言里面无出其右者,于是给人以C程序的速度必定最快的印象。但是忘记了这个速度快是来自C语言的系统编程特性,而在做科学计算时,并不需要过多地涉及到系统内核,因此C语言的长处在科学计算方面可以说并不能适当地发挥,相反,在数值计算方面,C绝对不是FORTRAN的对手,因为相对于C以系统编程为目的,FORTRAN是以科学计算为目的的,语言本身在设计之初,就考虑到了针对科学计算而进行优化,因此FORTRAN生成的可执行代码是高度优化的。
实际的运行效率方面的比较也表明了FORTRAN在科学计算方面的优越性。无论是国内还是国外,也无论是经典的串行机还是并行矢量机,大量的经验表明,在执行同一个科学计算任务时,C或C++代码的效率都低于FORTRAN代码。
除了常见的对于C有着高效的迷信之外,还常常有着对于FORTRAN是如何如何落后的偏见。当然这种偏见是有来源的,那就是曾经功勋卓著的FORTRAN77在很长一段时间里面,都缺乏进取心,使得迄今很多人提起FORTRAN,想到的就是在当今时代已经显得非常落后的FORTRAN77。实质上,FORTRAN标准在进入FORTRAN90时代之后,特别是现时的FORTRAN95版本,可以说只要是对于科学计算有用的特性,C和C++有的,现在FORTRAN95绝对不缺,而反过来FORTRAN95所具有的很多针对科学计算的特性,却是C和C++所不具有的。哪怕是C++最引以为傲的面向对象性质,FORTRAN2000也将全面引入。所以说,FORTRAN已经完全赶上了编程语言的潮流。
与程序运行的效能有关的另外一个重要方面,是程序语言能否支持程序的并行运行,在这点上,可以说FORTRAN表现了它的最大优势,因为FORTRAN95正是着力于获得并行计算的能力的一个版本。
由于现代科学计算的规模越来越大,计算并行化是一条不得不走的路线,现代计算机硬件的发展,也使得并行化具有实际的普及前景,因为不仅专门的大型计算机是并行的,现在的一般PC都可以拥有多个处理器,因此现代的从事科学计算的用户不得不掌握并行化计算的编程能力。
但是进行并行化编程所遇到的一个主要问题,就是任何过程编程语言都内在地使用线性存储模式,也就是一个数组的元素总是被认为按照数组元素的先后顺序而连续地存储在内存单位里面,这样一种模式就决定了这样的过程编程语言无法真正地实现对并行计算的描述。而FORTRAN95则完全改观了这种制约,因为在FORTRAN95里面对于数组以及数组运算建立了全新的面向并行化计算的概念,诸如纯过程的概念,逐元过程的概念,FORALL结构等等,都有效地摆脱了线性存储模式的制约,使得FORTRAN95成为描述并行计算的标准语言,特别是那些专用的数据并行化语言都纷纷采用FORTRAN作为基础语言,例如高性能FORTRAN(HighPerformanceFortran),FortranD,ViennaFortran,以及CRAFT等。这样就使得使用FORTRAN95编写的程序可以直接在这些数据并行化语言的平台上运行,而反过来使用这些专用语言编写的程序也可以毫不困难地转移到FORTRAN95平台上运行,这样一种局面使得FORTRAN在并行计算领域独领风骚。
综上所述,我们完全可以说FORTRAN95是进行科学计算的最佳语言,作为需要进行科学计算的科学与技术领域的工作人员,掌握FORTRAN95远比掌握C,C++等语言要重要得多,至于那些计算机符号代数与数值计算软件,例如MATHEMATICA,MAPLE,MATLAB,Macsyma,MATHCAD等等,只能说是进行科学计算的教学模型与辅助工具,由于它们都提供了现成的算法,因此可以使得初学者能够应用于一些简单的场合,真正要用它们来对付稍微大一点的问题,有经验的用户都知道,那会是一件非常痛苦的强人所难的事情。因此最终要自由地进行科学计算,则非FORTRAN莫属。
1.4FORTRAN的进步
下面我们介绍一下FORTRAN在历史上所取得的重要进步,特别是FORTRAN95有别于FORTRAN90的特征,更能够引导我们走向高性能的FORTRAN并行编程的领域。
1.4.1FORTRAN95的进步
FORTRAN的每一个进步,都意味着要把很多的语言特征归结为三类:
●新的语言特征;顾名思义,就是FORTRAN最新版本引入的全新语言。
●过时的语言特征;就是暂时在最新的FORTRAN标准里面仍然可以使用,而不会出现不兼容的情形,但是被指明为过时的语言特征,是在未来的下一个FORTRAN版本里面将要被淘汰的部分。
●废弃的语言特征。顾名思义,就是在过去的FORTRAN版本里面曾经出现过,但在现在的版本里面已经不许使用的语言特征。
下面分别介绍它们。
1.4.2新的语言特征
FORTRAN95所增加的新的语言成分包括全新的功能和对旧有功能的改进两个部分。它们主要包括:
●FORALL语句与结构。
●纯(PURE)过程。
●逐元(ELEMENTAL)过程。
●WHERE结构的扩展。
●默认初始化。
●NULL固有函数。
●CPU_TIME固有子例行程序。
●固有函数CEILING,FLOOR,MAXLOC,MINLOC的扩展。
●可分配数组的动态去分配。
●名称列表输入里面的注释。
●最小域宽格式说明。
●用于支持IEEE754/854浮点运算标准的某些修改。
下面分别予以说明。
1.FORALL语句与结构
FORALL语句与结构和纯过程这两个新的语言成分,主要是为了提高在多处理器系统上面的程序并行运行效率而引进的。
只要系统支持并行的赋值,FORALL语句以及结构,就能够自然地实现对一个庞大的数组的所有元素进行同时赋值,从而充分地利用了系统的并行效能。这个新特征的引入充分显示了FORTRAN在并行运算方面的努力。
2.纯(PURE)过程
PURE是一个完全新引入的过程属性。具有PURE属性的函数或子例行程序,除了返回值之外,将不具有任何的后效。也就是说,对于它的任意变元或全局变量,它都不改变它们的值,指针关联状态,以及数据映射,也不执行输入输出。
在FORTRAN95标准里面,一些场合要求其中的过程必须具有PURE属性。特别地PURE属性对于应用FORALL语句或结构进行并行赋值是必要条件。
3.逐元(ELEMENTAL)过程
逐元过程同样是执行并行运算的强大工具。把一个逐元过程应用到一个数组,就把这个针对数组的运算转化为对数组的所有元素的单个的运算,所有单个的结果再组合起来,返回一个同样形状的数组。
4.WHERE结构的扩展
WHERE结构经过扩展,可以包含一个FORALL结构的嵌套,而FORALL结构又可以包含WHERE语句或结构的嵌套。两者的配合使用具有强大的功能。
5.默认初始化
默认初始化可以应用于派生类型,包括哑元,这样就能保证具有指针成员的派生类型对象能够一直可以访问。从而避免了出现内存可分配,但是不能去分配的情形。
对于指针,可以使用新的固有函数NULL来给出初始的关联状态,也可以在使用数据之前,使用NULLIFY语句来获得初始化。
6.NULL固有函数
新引入的固有函数NULL的功能主要是给指针赋予一个初始的去关联的关联状态。NULL函数可以在一个类型声明语句当中使用,给定一个指针的初始去关联状态,也可以在一个结构构造器里面使用,用来给定其中指针成员的初始去关联状态。
7.CPU_TIME固有子例行程序
固有函数CPU_TIME用来测量一个程序或一段代码所消耗的处理器时间。这个函数的测量结果不一定是非常准确的,但在一些情形下是非常有用的。例如用来比较
不同代码的运行时间,从而比较它们的效率;也可以用来检测一个并行程序是不是真正地把一个变元作为一个数组来并行处理,从而评价它的并行效率。
8.固有函数CEILING,FLOOR,MAXLOC,MINLOC的扩展在FORTRAN90和高性能FORTRAN之间,某些固有函数以及相关函数存在某些不兼容,因为在高性能FORTRAN里面,在不同的变元位置增加了一个DIM函数。
在FORTRAN95里面,就放松了对于变元顺序的要求,这样在变元序列当中MASK和DIM的出现就可以是任意的了,从而保证了FORTRAN95与高性能FORTRAN的兼容性。
9.可分配数组的动态去分配
在FORTRAN95里面,当退出一个给定的作用域时,其中没有通过使用SAVE而得到保留的可分配数组,就自动地去分配,和使用DEALLOCATE语句的效果一样。这样就可以防止可能发生的内存遗漏,从而规范分配过程。
10.名称列表输入里面的注释
在名称列表输入纪录当中可以使用注释,从而方便了用户。
11.最小域宽格式说明
在使用数值的格式输出的时候,运用增强的输出格式编辑描述符,就可以对域宽进行极小化,从而避免输出时的白边。
12.用于支持IEEE754/854浮点运算标准的某些修改
在所有以前的FORTRAN版本里面,都不区分+0.和-0.,即正0和负0,在FORTRAN95版本里面,就能够区分这两者了,即在使用SIGN函数时,可以通过让第一个变元为0,而第二个变元为负号,就得到负0。
1.4.3过时的语言特征
FORTRAN95里面被划归为过时的语言特征,在FORTRAN90里面还是允许正常使用的,但是在FORTRAN95里面已经强烈地不提倡使用,因为它们在下一个FORTRAN版本里面会被彻底淘汰。这些过时的语言特征主要包括:
●算术IF语句。
●DO终止的某些形式。
●替代返回。
●计算GOTO语句。
●语句函数。
●可执行语句之间的DATA语句。
●哑长度字符函数。
●固定源码形式。
●字符型声明里面的CHARACTER*形式。
下面分别说明,并特别要注意它们为什么是多余的或容易产生错误的。
1.算术IF语句
算术IF语句的功能完全可以通过使用IF语句或IF结构来替代。
2.DO终止的某些形式
共享DO终止,或者不是使用ENDDO语句或CONTINUE语句的DO终止都是过时的,无论是从安全的角度,还是从清晰的角度,都最好使用具有不带标签的ENDDO语句的DO结构块形式。
3.替代返回
替代返回强烈地依赖标签,是不值得提倡的,而且同样的功能完全可以通过CASE结构来实现。
4.计算GOTO语句
计算GOTO语句完全可以使用CASE结构来代替,而且CASE结构还具有比计算GOTO语句更加广泛的功能。从结构化编程的角度来看,也应该使用CASE结构,而不是完全非结构化的,带有早期与系统相关特征的计算GOTO语句。
5.语句函数
内部函数就具有语句函数的许多特征。而语句函数非常容易与赋值语句相混淆,所以语句函数也是不提倡使用的。
6.可执行语句之间的DATA语句
如果在程序的可执行部分使用DATA语句的话,会容易让人产生一种错觉,即DATA语句能够在程序的执行过程当中进行赋值,而实际上,DATA语句只能用于数据的初始化,因此DATA语句最好还是只用于程序的说明部分。
7.哑长度字符函数
哑长度字符函数要求在调用程序当中声明函数的名称,它完全可以通过运用具有显式界面或动态字符长度的子例行程序或函数来替代。
8.固定源码形式
固定源码形式完全是由早期的卡片纸带式输入输出方式所决定,而现在卡片纸带式输入输出早已经不再使用,因此这种源码形式必定是要被淘汰的。
9.字符型声明里面的CHARACTER*形式
在字符型声明语句当中用来说明字符长度的CHARACTER*完全是多余的,一般提倡采用更为合乎英语习惯的形式。
1.4.4废弃的语言特征
在FORTRAN90里面还可以使用的语言特征有些已经被FORTRAN95完全废弃了,因此要特别留意它们,以免出现源代码无法在FORTRAN95系统里面调试通过的情况。
这些被FORTRAN95废弃的语言特征主要包括:
●实型和双精度实型的DO变量。
●从块的外部分支到块内部的ENDIF语句。
●PAUSE语句。
●ASSIGN语句,带标签的GOTO语句。
●nH编辑描述符。
为了能够阅读使用FORTRAN90以及更早版本的源代码,下面还是分别予以简要的说明。请注意它们遭到淘汰的原因所在。
1.实型和双精度实型的DO变量
实型和双精度实型的DO变量或循环控制的DO参数都是难以移植的,而且也是很少用到的。因此现代的FORTRAN版本都要求DO变量为标量整型变量。
2.从块的外部分支到块内部的ENDIF语句
从块的外部分支到块内部的ENDIF语句对于语句的执行序列的控制,是完全不必要的,也是不规范的,因此已经被完全淘汰了。
3.PAUSE语句
PAUSE语句用于把一个正在运行的程序挂起来,直到系统或操作重新开始运行。它的功能完全是多余的,因为WRITE语句可以发送消息到任何设备,例如操作控制台或终端,而READ语句则可以等待或接收来自同一个设备的消息。它们的配合使用就可以替代特别的PAUSE语句。
4.ASSIGN语句,带标签的GOTO语句
ASSIGN语句用来给一个整型变量赋予一个语句的标签。
它的一般用途就是,在程序的运行过程当中,通过ASSIGN语句就可以给该整型变量赋予分支目标语句的标签,从而给程序提供一种动态分支的能力。
然而整型变量除了可以具有标签值之外,还有可能具有一般的整数值,这就会容易导致程序错误,也使得程序难以阅读。
实际上ASSIGN语句,以及带标签的GOTO语句的功能,都可以由内部过程实现,因为ASSIGN语句无非就是纪录了一个可重用代码块完成运行后的返回点。
ASSIGN语句还可以把一个formAT语句的标签动态地赋予一个整型变量,然后该变量就可以用作WRITE,READ,PRINT语句的格式说明符。不过这个功能也可以通过把字符型变量,数组,以及常量用作格式说明符而得到实现。总之,标签的使用总是不合时宜的。
5.nH编辑描述符
使用这个编辑描述符非常容易导致错误,因为跟在该描述符后面的字符数目很容易计算错误,而如果使用字符常量编辑描述符来行使相同的功能的话,则根本不需要计算字符数目。

发表于 2005-3-19 02:44:24 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

[这个贴子最后由anyone在 2005/03/20 07:26am 第 2 次编辑]

看来是要单挑我, HEHE.
这不过是一篇鼓吹FORTRAN的文章, 太长了, 没法仔细研究. 只说几点.
关于执行速度:
所谓FORTRAN执行速度比C高, 基本是误导. FORTRAN语言不能在电脑上直接运行. 必须先要翻译成机器语言. 不幸的是, 这项翻译/优化的工作是别人用C来作的. 不要告诉我那些搞编译器的都是活雷峰, 好的优化方法都只给FORTRAN用, 而不用在C的编译器上. 对执行效率我个人的经验, 对一般的计算为主的程序, 在主流机器上, 用比较好的编译器, FORTRAN和C如果做同样东西而且写的基本一样的话, 执行速度基本也是一样的. 这很容易理解, 因为相关的优化方法相对比较成熟, 大家用的都是一样的. C++问题复杂一点, 时间关系就不说了.
描述数学语言的自然性方面:
自从有了面向对象的语言出现以后, 已经不是什么了不起的东西了. 连所有运算符(+-..)都可以根据不同对象重新定义. 在FORTRAN95里你可以用"+"把两个矩阵直接加起来, 但你能把两个链表用"+"直接加起来吗? (这句有错, 见后面回贴)
FORTRAN的进步:
除了并行运算方面不是很了解, 其他的改进基本是把C/C++的好东西拿过来, 没什么革命性的. 即使FORTRAN2000全面引入面向对象性质, 也只是搞了个新的"C++". 且不说现在有谁有成熟的支持FORTRAN2000的编译器? 几年前不错的C++编译器就已经遍地都是, 很多还是免费的.
个人意见总结:
FORTRAN在科学计算里是不错的, 但并不比C/C++更好. 在开发大型程序方面, 至少在目前, 因为面向过程的特点, 不如C++. 从学习角度来说, FORTRAN 比C/C++更容易. 目前FORTRAN在CFD里还有很大市场, 但从总体来看, FORTRAN在衰退, 今后语言更新/技术支持上都可能会有问题.

发表于 2005-3-19 17:56:29 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

[这个贴子最后由wice在 2005/03/19 07:31pm 第 1 次编辑]

二楼对Fortran了解不够
关于编译我不太了解,但在描述的自然性上,fortran还是比较好的。
而你所谓的“自从有了面向对象的语言出现以后, 已经不是什么了不起的东西了. 连所有运算符(+-..)都可以根据不同对象重新定义. 在FORTRAN95里你可以用"+"把两个矩阵直接加起来, 但你能把两个链表用"+"直接加起来吗?”
在90下就可以实现,定义一个接口就可以了,根本就不需要面向对象的知识,如果不能真正了解“面向对象”的含义,不要乱说。90的自定义数据构造就含有面向对象的意思。看你怎么使用了。欢迎批评我,我只是一个大四的学生!
发表于 2005-3-19 18:13:43 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

Fortran和C的争论到处都是。不过我个人认为,C和C++应该更胜一筹。
上学期我去听了学院的几个报告,都是美国的研究机构和学者作的。当时就有学生问他们关于数值计算的语言。他们的回答都很统一,他们n(n<10)年前就不用Fortran了。他们说fortran过时了,而且还说,根据他们自己和对外交流的经验,美国这个领域内作数值计算的用C和C相关的语言已经占了绝大多数。
事实胜于雄辩,你们就别争了。这种事情跟在美国人屁股后面应该不会错的。
发表于 2005-3-20 01:47:53 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

下面引用由wice2005/03/19 05:56pm 发表的内容:
二楼对Fortran了解不够
关于编译我不太了解,但在描述的自然性上,fortran还是比较好的。
而你所谓的“自从有了面向对象的语言出现以后, 已经不是什么了不起的东西了. 连所有运算符(+-..)都可以根据不同对象重新 ...
说漏了, HOHO.
忘了在FORTRAN90下就可以实现OPERATOR OVERLOADING. 这点你对. 不过我认为OPERATOR OVERLOADING是面向对象的特征之一, 虽然不需要定义OBJECT. 不过这不重要.
我没说FORTRAN90没有面向对象能力, 只是比起C++差远了. 比如不支持对象的继承和多态, 也不支持模板(TEMPLATE)(TEMPLATE和OPERATOR OVERLOADING类似, 也不需要定义OBJECT). 而多态和模板是实现描述的自然性非常重要的工具. 如果谁想了解这两个概念, 可以随便找一本C++看看, 就不多谈了.
我用FORTRAN90写CFD有7-8年了, 写过2叉树,链表,HASH TABLE 等等. 这些都要用到F90的自定义数据结构, 指针, 自调用等新功能.真正用C++写CFD是从去年处开始. 基本上来讲, 不会因为对F90不了解而产生偏见. 当然也不是说我说的就一定是对的, 大家互相讨论可以共同提高.

 楼主| 发表于 2005-3-20 18:39:13 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

    anyone,这篇文章是我针对你关于Fortran和C++的看法而专门找的,我想说的是,Fortran目前的确有“要被淘汰的感觉”,前几天我在南京的各大书店逛了一下,发现关于Fortran的新书只有三本,而且其中一本是主要介绍Fortran77的!

    虽然我还没有用过C++,但说实话,我打从心里不服气,Fortran90以后加入了“面向对象”概念以后,功能上有比较大的飞跃,我以前作的很多函数因为过多的垃圾代码都需要重写了。我认为Fortran不比C++差。
发表于 2005-3-21 09:57:37 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

[这个贴子最后由wice在 2005/03/21 09:59am 第 1 次编辑]

我找计算机系的硕士生问了一下。他说“关于计算速度关键看编译时是否优化,很多语言都是可以利用自身来做编译器的”,关于这个我不是很理解。不知anyone可否给出实证来证明FORTRAN编译器是用C/C++来做的
还有一楼的原文是一本讲FORTRAN95的书的序章
发表于 2005-3-21 17:42:06 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

我算a+b的时候还是习惯用fortran,
其他语言也学不会了
发表于 2005-3-22 00:49:25 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

下面引用由wice2005/03/21 09:57am 发表的内容:
我找计算机系的硕士生问了一下。他说“关于计算速度关键看编译时是否优化,很多语言都是可以利用自身来做编译器的”,关于这个我不是很理解。不知anyone可否给出实证来证明FORTRAN编译器是用C/C++来做的
还有一 ...
我不是CS专业, 也不会写编译器, 我所说的是根据我所了解的加上一些常识.
编译器只是把高级语言翻译成机器语言, 并不需要用自身来做. 原则上如果一种语言能提供写编译器所需要的功能, 比如字符串的处理, 相关的底层机器涵数的调用, 就可以用来写编译器. 如果没搞错, C编译器一般是用C写的. 当然这里有个先有鸡还是先有蛋的问题, 第一个C编译器应该是用其他语言(比如汇编/机器)写的, 可能只有基本功能, 也没优化. 后面再用C重新写个完整的. 具体怎么做我也不知道.
为什么认为FORTRAN编译器是用C/C++来做的? 基本上是根据常识. C在写编译器方面有比FORTRAN强得多的功能(比如字符串的处理). 编译器要和操作系统打交道, 而一般的操作系统也是用C写的(UNIX主要部分肯定是用C写的, WINDOWS相信也不例外). 编译器一般是搞CS的人做的, 而C/C++是他们喜欢用的语言.
"给出实证来证明FORTRAN编译器是用C/C++来做的"还真不是很容易, 因为写软件的人一般并不告诉你他是用什么语言写的. 还好我找到一个旁证, 也许能说明问题:
这是 NAGWare f95 Compiler FAQ 里的一段话 ( http://www.nag.co.uk/nagware/NP/doc/faq.asp&#35;FAQQ4 ):
4. Which C compiler do we need?
Most of the NAGWare f95 ports use the C compiler which is supplied with the machine that it is used on.
On Sun (SPARC) Solaris, either the Sun ANSI C Compiler or the GNU C Compiler may be used. You must specify which C compiler you have when you purchase NAGWare f95 (the implementations are different).
NAG 是UNIX上很流行的一种商用FORTRAN编译器.
发表于 2005-3-22 03:45:23 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

这个问题不想再讨论下去了, 再往下基本都是争论一些无关紧要的细节. 最后啰嗦几句.
忽然想到GNU. 如果你没听说过, GNU是最著名的开源软件基地. 他们提供各种版本的C, C++, FORTRAN免费编译器. 看了一下, 不出所料, GNU各种编程都要求尽可能用C ( http://gnu.planetmirror.com/prep/standards_toc.html&#35;SEC_Contents ). 我也下载了他们的源代码扫了一眼, FORTRAN编译器果然是用C写的.
至于C++是否适用于科学计算, 6-7年前大家讨论的很多, GOOGLE一下会发现相关文章基本都是那时候的. 我没看到2000以后的文章继续讨论这个问题. 相信已经没有讨论的必要了. 而愈来愈多的人用C++进行科学计算已是不争的事实.
如果你注意读我前面的回帖, 对C++的运算速度我并没有给出明确结论. 之所以这样是因为面向对象的编程(C++)和面向过程的编程(FORTRAN90)是完全不同的, 很难简单的比较. 而且即使对同一个问题, 用面向过程的编程,大家写出来的东西相差并不是很大, 而用面向对象的编程,由于对象设计的不同, 十个人就可能有十个不同的方案. 新手和对C++不是很了解的人, 是有可能滥用面向对象的功能, 没必要的进行多层次间接调用, 从而造成时间上的大量损失, 导致程序执行速度大大下降. 即使是高手, 有时为了实现某些面向对象的功能, 和传统面向过程的编程相比也可能会损失一些时间(比如5%-10%), 而这点时间上的损失和面向对象编程对开发大型程序所带来的编程效率的提高, 可靠性, 稳定性, 可维护性, 可扩展性相比是完全可以忍受的.
发表于 2005-3-22 15:48:14 | 显示全部楼层

[转载]Fortran闲谈。(建议那些认为在数值计算上Fortran不如C++的人进来看看)。

做CFD之前用的C
后来做CFD我一直用f90的,毕竟f77太过时了。但是f90的编译器不多,GNU的还没实现,所以后来就只好转到c++
即便f90加入了一些自定义数据结构和所谓的面相对象支持,但是我还是深感这些东西根本还称不上是“面相对象”。至于加入的指针支持,相比c的指针还是限制太多,不够灵活
唯一感觉fortran中比较有用的是对数组的直接操作很方便
其它诸如底层支持并行的功能,实际上很难用到,因为目前趋势是分布式并行,而不是共享内存并行,那些特性就用不到了。
优化我不懂,不发表意见
对于程序设计来说,过程化的fortran确实落后了,非常不适合大型软件的开发。c/c++是一个更合适的选择,目前很多大型计算软件都是c/c++编写,同时应用混编技术,拿fortran编写某些子函数,以便利用现有资源。要知道目前c++编写的各种类库非常丰富,就比如一个case参数设置文件,如果用fortran编写,很费劲,同时对参数文件格式要求比较严格,但是如果利用现有的c++库,那么就非常简单,而且要求很松。
如果小型代码,那倒无所谓了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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