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

4

使用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 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

我猜测这与Fortran内置函数不能正确处理索引为0的数组有关,因为以这种方式声明数组不是标准的Fortran风格(但仍然被允许!)。是否有人能够确认这一点或提供解决方法?
2个回答

8
你的数组a确实从索引0开始,但你没有使用它。你搜索了数组abs(a(:))的最小值。这个匿名的数组表达式默认从1开始,因为所有的数组都是这样的。
但即使你使用了a,结果也是一样的,并且与Fortran中数组参数传递的工作方式一致。
Fortran标准明确规定: 返回的i下标在1到ei的范围内,其中ei是ARRAY的idimension的范围。如果ARRAY的大小为零,则结果的所有元素都为零。 如果你使用了假设形状的参数,则不会自动传递下限。例如,如果你有自己的函数。
  function f(arg)
    real :: arg(:)

arg始终从1开始,无论实际参数在调用代码中的位置如何。

您可以更改它以从其他某个值开始

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

并且它将从该值开始进行索引。


1
太棒了,谢谢。我想我的假设是a(:)指代数组的全部范围,无论它是什么,但当然不是这样的。干杯! - Makkasu

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接