有什么方法可以找到包含特定实数的数组的元素



在Fortran代码中,我有一个数组a,其值的范围从0.01.2一致,我正在寻找最接近1.0的值的索引。

Fortran中似乎没有任何内部函数可以做到这一点,所以我用MINLOC做了一个巧妙的变通方法:(注意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

这似乎奏效了。

我对实现这一点的其他方法感兴趣,所以有几个问题:

  • MINLOC是如何工作的
  • 是否有其他例程可以直接到达那里(即不必制作第二个数组)
  • 其他语言是如何处理的

谢谢。


EDIT:我之前链接到这篇文章,称其为寻找MINLOC替代品的部分动机,但由于一些评论者指出它有些无关紧要,因此已将其删除。包括它似乎有损于我的目标,即寻找这种方法的替代品。

这不会比您的解决方案运行得更快,但它确实缩短了代码:

index_1 = minloc(abs(a - 1))

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

如果您需要在此数组中重复搜索不同的值,那么首先对数组a进行排序,然后执行二进制搜索会快得多。这将把运行时间从O(n)减少到O(log(n)),其中n是a的大小。

首先要注意的是,链接的文章并没有批评MINLOC本身的性能,而是批评它发现了特定值的性能。

在Fortran 2008中,有一个用于此目的的内在FINDLOC,但它可能不适合这个问题。然而,对于参考文章中的问题,这将是正确的做法。另请参阅Fortran findloc内部

速度缓慢的一个原因是,在调用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

最新更新