1. C++语言和Fortran语言的发展背景
在程序设计语言的发展过程中,FORTRAN 语言被认为是科学计算的专用语言。后来推出的FORTRAN90 和FORTRAN 95 版本也不例外,它们虽然可以完全实现C++语言同样的功能,然而其软件开发环境和软件的集成性等方面都远不如C++ 语言。近年来,随着计算机软硬件技术的发展,数据结构、数据库管理技术、可视化与计算机图形学、用户接口系统集成以及人工智能等领域的成果被逐渐应用到结构分析软件中,结构分析软件的设计并不仅仅局限于单一的科学计算需要涉及众多的软件开发领域。C++ 语言可以提供这类软件开发所需的功能,而用FORTRAN 90 却很难实现,另一方面从软件的编程环境来看,目前FORTRAN 90 的编译器极少,而C++ 语言的编译系统相当普及,可以运行在各种机型上,便于实现跨平台的软件系统集成。
2. C语言和Fortran语言的差异
由于两者产生的背景不同,它们是存在差异的,在比较了几组源代码之后,主要有以下体会:
C 最大的优点在于灵活,不但可以藉由 struct 来定义新的数据结构 ,同时 C 的pointer 更可以让我们自由而且有效率地处理大数据。而在 UNIX 系统 中,由于整个操作系统绝大部分就是 C 写出来的,故我们也有方便的 C 函数库, 直接使用系统资源与享受系统带来的服务,以做到一些低阶、快速的动作。而FORTRAN从一开始就用于科学计算,它与C的差异主要表现为:
* 复数运算的速度
* 程序参数与字串
* 内存的动态管理
* 多维阵列的处理
* 函数调用与参数传递
2.1. 复数运算的速度
在进行复数运算的时候,C++ 可以定义复数的 class,还可以重新定义所有的四则运算式,复杂的算式也可以做到由一个表达式来解决。但它的重新定义复数四则运算是用函数来做的,使用函数来调用其速度很慢,除非采用 inline function 的方式,但会遇到以下的问题:要先将这个算式拆解,分别算过后再重组结果,故表面上程序代码很简洁,但实际上是 compiler做了很多工作,还是要付出相当的计算时间代价的。
至于 Fortran,最大的优点在于复数 (complex number) 的运算,复数是 Fortran 的基本数据类型之一,这正是 C 所缺乏的 (C 基本上只有实型与整型类型而已)。 虽然C 也可以由 struct 的定义,达到复数四则运算的目的,但 却很可能牺牲了程序效能,或者是程序写起来相当繁杂降低可读性。因此,在大量而且要求高速的复数运算场合, Fortran 实际上比 C 还要适合。
int main(int argc, char **argv) { int a, b, c; a = atoi(argv[1]); b = atoi(argv[2]); c = atoi(argv[3]); } |
而程序执行时,参数就是这样传入: a.out 12 15 18
Fortran 却没有办法 ,要传入任何参数,只能透过对话的方式:
integer a, b, c c ------------------------------------ write(*,*) ''please input integer a:'' read(*,*) a write(*,*) ''please input integer b:'' read(*,*) b write(*,*) ''please input integer c:'' read(*,*) c c ------------------------------------ end |
2.3. 内存的动态管理
C 可以动态分配存储空间给任何数据类型,而Fortran 却不行。
例如:
float *c_function(int cnt) { float *a; a = malloc(sizeof(float) * cnt); /* * 操作 array a. */ return a; } |
program fout c ---------------------------- integer cnt parameter (cnt^P00) real a(cnt) call f_routine(cnt, a) end c ---------------------------- subroutine f_routine(cnt, a) c ---------------------------- integer cnt real a(cnt) c c 操作 array a. c end |
这里的 parameter 是设定变数的固定值,其作用就相当于 C 的 const 一样,经设定后的参数就是一个无法改变其值的常数了。有的时候,在某个函数中我们临时需要一个暂存阵列,但等到计算完成离开函数后,该阵列就没有用了,这在 C 可以做的很划算,即进入函数时malloc() 一个阵列,离开前再 free() 掉它。但在 Fortran 中却别无选择,一定要在 MAIN__ 里头先将暂存阵列配置好,再一起传入 subroutine 中。
2.4. 多维阵列的处理
不论是在 C 或 Fortran, 所谓的多维阵列实际上只是一个很长的一维连续存储空间,经过分割后当做多维阵列使用。例如,一个 C 的二维阵列声明如下:
double a[12][10]; |
|<--- 10 ---><--- 10 ---> .... <--- 10 --->|
|<<-------------- 共 12 组 --------------->>|
所以它实际上是一块 12*10*sizeof(double) bytes 的连续存储区块,而经由以上的声明,compiler 便知道当使用到它时,要将分割成每单位元素为 sizeof(double),每 10 个单位一组,而总共 12 组的一个二维阵列,则当我们使用阵列的 index 来存取阵列元素时, compiler 也会自动算好该元素阵列在此存储区块的位置,因此就能很方便地使用。
Fortran 也是如此,但有一个很大的不同,它的存储区块分割配置的方式是与 C 反向的。例如声明一个二维阵列如下:
double precision a(12,10) |
|<--- 12 ---><--- 12 ---> .... <--- 12 --->|
|<<--------------- 共 10 组 -------------->>|
因此,如果我们要在 Fortran 中配置一个与上头那个 C 一模一样的二维阵列时,实际上应该要将其 index 反过来:double precision a(10,12)
除此之外, C 的阵列 index 一律是从 0 开始,对于一个有 N 个元素的阵列,其最后一个 index 是 N-1,且每个阵列元素的 index 值差 1。 Fortran 不一定,要看怎么声明了。例如声明一个阵列如下:
double precision a(100) |
double precision a(11:110) |
这还是一个一维阵列,共 100 个元素,但第一个元素的 index 是 11, 最后一个是110 .在这里我们可以看到, (idx1:idx2) 这样的叙述在 Fortran 中就是用来指定一个阵列的范围。
2.5. 函数调用与参数传递
C 的函数调用就只有一种方式,函数可以传入参数,也可以返回值,例如:
void c_function1(int a, float *b) { ........ } int c_function2(int a, float *b) { int r; ........ return r; } int main(void) { int a, r; float b; c_function1(a, &b); r = c_function2(a, &b); } |
subroutine f_function1(a, b) integer a real b ........ end integer function f_function2(a, b) integer a real b ........ f_function2 = .... end program fout integer a, r, f_function2 real b c ----------------------------------- call f_function(a, b) r = f_function2(a, b) end |
integer f_function2 |