NCL循环和条件判断

循环语句

处理实际问题时,经常碰到许多具有规律性的重复操作,此时就需要在程序中重复执行某些 语句。能否继续重复,决定循环的终止条件。循环结构是在一定条件下反复执行某段程序的 流程结构,被反复执行的程序被称为循环体 [1] 。 循环语句是由循环体及循环的终止条 件两部分组成的。

与其他语言类似,NCL中循环可以分为二种,指定运行次数的循环(do循环)以及指定继续 运行条件(或停止条件)的循环(do while循环),基本上NCL中的循环与Fortran一致。

do 循环

模型:

do i = start, end, stride
    ;; 代码段
end do
  • i为循环变量,start,end,stride为循环变量的初值,终止值和步长
  • 初值,终止值和步长都可以为表达式,但其结果必须为标量
  • 循环变量的步长可以省略,使用时必须为正
  • 省略步长的循环中,若初值大于终止值,循环不会被执行;若初值等于终止值,循环将被执行一次
  • 使用步长的循环中,初值可以大于终止值,为后向循环

do while循环

模型:

do while (标量逻辑表达式)
    ;; 代码段
end do
  • 当标量逻辑表达式的值为真( True )时,执行循环体代码段
  • 标量逻辑表达式指的是逻辑表达式的值必须为标量,若为序列或数组将引发异常
  • 标量逻辑表达式的值不能为缺测值
  • .and..or. 的短路求值同样发生
  • 相比于do循环,此循环结构适用于循环次数未知的情况

循环的控制

NCL中可以使用 continuebreak 关键词对循环进行控制,它们的含义与C语言一致。

  • continue 语句用于终止本次循环,继续进行下一次循环或循环判断
  • break 语句用于终止本层循环,当循环内代码执行到break时,循环便被终止

循环结构的注意点

由于解释性语言的在效率上的缺陷,因此对于循环的使用要做到“能不用则不用、一定要用注 意优化”。

避免不必要的循环

在NCL中的循环效率不高,应尽量减少循环,特别是大循环、高层嵌套循环的使用。 那么该如何减少循环的使用呢?最好的方法是使用NCL函数,事实上 我们许多的数组运算和操作,在NCL中都有函数可以直接的进行。一些 新手由于对NCL函数不熟悉,经常写出一些没必要的多层循环结构。

优化循环结构

  1. 多重循环中,可能的情况下,将长循环放在内层,短循环放在外层,可节省循环时间
  2. 避免在循环体内改变循环变量,防止出现不期待的循环结果
  3. 循环嵌套控制在3层以内,过多的循环层数使代码变得难以理解

条件判断if语句

NCL提供if语句来进行流的控制,NCL中的if语句包含两种:

if-then语句

模型:

if ( 标量逻辑表达式 ) then
    ;; 语句
end if

if-then-else语句

模型:

if( 标量逻辑表达式  ) then
    ;; 语句
else
    ;; 语句
end if

注解

需要强调的,也是导致if语句经常报错的是,标量逻辑表达式的结果必须是单个标量值并且不能为缺测。

if语句的嵌套

NCL中允许对if语句进行嵌套,然而NCL中并没有else if语句,但这并不妨碍我们在NCL中使 用else if,通过将else和if放置在一行上,可以构成else if,尽管这并不是真正意义上的 else if,而是对if语句的嵌套。因而这个if后面同样需要end if。

if ( 标量逻辑表达式 ) then
    ;; 语句
else if (标量逻辑表达式 ) then
    ;; 语句
else if ( 标量逻辑表达式 ) then
    ;; 语句
else
    ;; 语句
end if
end if
end if

关于缺测

逻辑表达式中已经提到在NCL中的逻辑值不仅包含True,False,还包含了missing。 而在if语句中,逻辑表达式的值并不允许是missing,事实上使用以下语句判断元素是否为 缺测时,将出现错误:

if( a(i) .eq. a@_FillValue) then
     ...

引发异常:

错误

fatal:The result of the conditional expression yields a missing value. NCL can not determine branch, see ismissing function

在该if语句中,逻辑表达式的值将是missing,所以引发异常。 正确的判断是否为缺测的方式是使用 ismissing 函数

if(ismissing(a(i))) then
    ...

关于数组逻辑表达式

既然if语句的逻辑表达式必须要求单标量值,那么数组逻辑表达式有什么好的方法可以在 if语句中使用呢?一些函数( any, all, ismissing )能提供有益的帮助。

  • all ,当所有的逻辑元素为真时,all函数返回真
  • any ,只要有一个逻辑元素为真,any函数返回真
  • ismissing ,对所有的数组元素判断其是否为缺测,并生成与数组同样大小形状的逻辑值,合理利用ismissing函数能在很大程度上避免if语句错误发生

关于短路求值

逻辑表达式中已经提到短路求值的概念,由于逻辑表达式从左到右执行,在.and. 和.or.中, 如果逻辑表达式的第一项就能确定逻辑表达式的值,那么后面的逻辑表达式将不被求值。 因此,合理地布局if语句中的多个逻辑表达式的位置,有益于避免错误和减少不必要的运算。

比如:

if((i .lt. dimsizes(a)) .and. (a(i) .gt. 10 )) then
    ...
end if

以上语句将避免索引值超出变量a的索引范围。

[1]http://baike.baidu.com/view/961969.htm
../_images/donate2.png

评论