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

Mak*_*asu 3 c arrays fortran min intrinsics

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

real(kind=dp), dimension(:), allocatable :: a 
allocate(a(0:50))
Run Code Online (Sandbox Code Playgroud)

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

minloc(abs(a(:)))
minval(abs(a))
Run Code Online (Sandbox Code Playgroud)

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

Index i    a(i) 

39         0.04667    
40         0.02222    
41         0.00222           !This was clearly the minimum value
42         0.02667

MINLOC = 42
MINVAL = 0.00222
Run Code Online (Sandbox Code Playgroud)

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

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

Vla*_*r F 7

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

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

Fortran标准明确指出:

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

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

  function f(arg)
    real :: arg(:)
Run Code Online (Sandbox Code Playgroud)

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

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

  function f(arg)
    real :: arg(-42:)
Run Code Online (Sandbox Code Playgroud)

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


roy*_*vib 5

有两种简单的方法来处理调整从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
Run Code Online (Sandbox Code Playgroud)