MINLOC是否适用于从索引0开始的数组? (Fortran 90/95)

使用C一段时间后,我回到Fortran并在我的代码中将数组从索引0分配到N:

real(kind=dp), dimension(:), allocatable :: a allocate(a(0:50)) 

我需要找到数组最小绝对值的索引,所以我使用MINLOC,并检查这个我将它与MINVAL进行比较:

 minloc(abs(a(:))) minval(abs(a)) 

MINLOC的结果是指数42但MINVAL的结果相当于41 。 以下是输出的相关部分:

 Index ia(i) 39 0.04667 40 0.02222 41 0.00222 !This was clearly the minimum value 42 0.02667 MINLOC = 42 MINVAL = 0.00222 

我假设这与Fortran内部没有正确处理索引为0的数组有关,因为以这种方式声明数组不是标准的Fortran样式(但它仍然是允许的!)。

任何人都可以确认这一点或提供解决方法吗?

你的数组确实从索引0开始,但你没有使用它。 您搜索了最小数组abs(a(:)) 。 此匿名数组表达式从1开始,因为所有数组都默认执行。

但即使您使用a结果也是相同的,并且与数组参数传递在Fortran中的工作方式一致。

Fortran标准明确指出:

返回的i下标位于1到ei的范围内,其中ei是ARRAY的idimension的范围。 如果ARRAY的大小为零,则结果的所有元素都为零。

如果使用假定的形状参数,则下限不会自动与数组一起传递。 例如,如果您有自己的function

  function f(arg) real :: arg(:) 

无论调用代码中的实际参数在何处开始, arg始终为1。

您可以将其更改为从其他值开始

  function f(arg) real :: arg(-42:) 

它将从该值开始编入索引。

有两种简单的方法来处理调整从minloc()获得的索引的复杂性:一种是简单地为所有索引添加lbound() – 1,另一种是使用具有从1开始的索引的数组指针。 示例代码可能如下所示:

 program test implicit none integer, allocatable, target :: a(:,:) integer, pointer :: anew(:,:) integer :: loc(2) allocate( a( 0:4, 2:5 ), source= 10 ) !! make an array filled with 10 a( 2, 3 ) = -700 !! set the minimum value loc(:) = minloc( a ) !! minloc() receives "a" with 1-based indices print *, loc(:) !! so we get [3,2] print *, a( loc(1), loc(2) ) !! 10 (wrong result...) !! Method (1) : adjust indices manually loc(:) = loc(:) + lbound( a ) - 1 print *, a( loc(1), loc(2) ) !! -700 (now a correct result) !! Method (2) : use array pointer with 1-based indices anew( 1:, 1: ) => a loc(:) = minloc( anew ) print *, loc(:) !! we get [3,2] again print *, anew( loc(1), loc(2) ) !! -700 (this time, no need to adjust indices) end program