有哪些方法可以找到包含特定实数值的数组元素?

What methods are there for finding the element of an array containing a specific real value?

在 Fortran 代码中,我有一个数组 a,其值统一从 0.01.2,我正在寻找最接近 1.0

在 Fortran 中似乎没有任何内在函数可以做到这一点,所以我用 MINLOC 做了一个 hacky 解决方法:(注意 tempa 的形状相同)

do i=1,n
  temp(i) = 1.0 - a(i)
end do
loc = 0    !note that loc is an integer array, declared as 'loc(1)'
index_1 = minloc(abs(temp(:))) !this is the index of a closest to 1.0

这似乎可以解决问题。

我对实现此目的的其他方法很感兴趣,所以有几个问题:

谢谢。


编辑:我之前链接到 this article,将其作为寻找 MINLOC 替代方案的部分动机,但已将其删除,因为一些评论者指出它有些无关紧要。包括它似乎有损于我的目标,即找到该方法的替代方法。

首先请注意,链接的文章并没有批评 MINLOC 本身的性能,而是批评了寻找特定值的性能。

在 Fortran 2008 中有内在的 FINDLOC 用于这个确切的目的,但它可能不是解决问题的正确方法。但是,对于所引用文章中的问题,这将是正确的做法。另见 Fortran findloc intrinsic

速度缓慢的一个原因(立即可见)是调用 MINLOC(abs(temp(:))) 时必须为 abs(temp(:)) 创建一个临时数组。另一个原因是当找到匹配项时,文章中的循环可以立即退出。然而,这对您的申请并不重要。

内在的 MINLOC 本身可能并不慢,它只是在一个简单的循环中搜索数组。

这些结果也会因编译器而异。您检查过编译器的性能差异了吗?

最后的建议:只写一个避免临时数组的简单循环。


用于查找最接近的浮点元素的简单循环。简单的 CS101 内容。

min_diff = huge(1.0)
idx = 0

do i = 1, size(a)
  diff = abs(a(i)-to_find)
  if ( diff < min_diff) then
    idx = i
    min_diff = diff
  end if
end do

这不会 运行 比您的解决方案更快,但它肯定会缩短代码:

index_1 = minloc(abs(a - 1))

虽然您不必以这种方式自己设置临时数组,但编译器仍会在幕后进行设置。 MINLOC 靠蛮力工作:找到最小值没有捷径。

如果需要在这个数组中反复查找不同的值,先对数组a进行排序,然后进行二分查找会快很多。这会将 运行 时间从 O(n) 减少到 O(log(n)),其中 n 是 a.

的大小