【问题标题】:Does MINLOC work for arrays beginning at index 0? (Fortran 90/95)MINLOC 是否适用于从索引 0 开始的数组? (Fortran 90/95)
【发布时间】:2015-06-17 11:22:36
【问题描述】:

在使用 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 样式(但仍然允许!)。

谁能证实这一点或提供解决方法?

【问题讨论】:

    标签: c arrays fortran min intrinsics


    【解决方案1】:

    您的数组 a 确实从索引 0 开始,但您没有使用它。您搜索了最少的数组abs(a(:))。这个匿名数组表达式默认从 1 开始。

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

    Fortran 标准明确规定:

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

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

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

    arg 总是从 1 开始,无论实际参数在调用代码中的哪个位置开始。

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

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

    它会从那个值开始被索引。

    【讨论】:

    • 太棒了,谢谢。我想我的假设是 a(:) 指的是数组的整个范围,不管那可能是什么,但当然不是。干杯!
    【解决方案2】:

    有两种简单的方法可以处理调整从 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      相关资源
      最近更新 更多